Почему curl_errno() возвращает 0 при наличии ошибок в сочетании с curl_multi_init()?

У меня есть список доменов, которые я хочу проверить, активны они или нет. Я могу проверить каждый по отдельности, но мне трудно заставить пакет работать.

  $c200= array();
  $c301= array();
  $c302= array();

$urls=array();
  foreach (new SplFileObject("oList.txt") as $line) {
    $urls[]=$line;

}
//print_r($urls);

$mh = curl_multi_init();
foreach ($urls as $key => $value) {
  $ch[$key] =curl_init($value);
  curl_setopt($ch[$key], CURLOPT_HEADER, true);
  curl_setopt($ch[$key], CURLOPT_TIMEOUT, 10);
  curl_multi_add_handle($mh, $ch[$key]);

}

do{
  curl_multi_exec($mh, $running);
  curl_multi_select($mh);
}while ($running > 0);

foreach (array_keys($ch) as $key) {

  echo curl_getinfo($ch[$key], CURLINFO_HTTP_CODE);
  echo "\n";

  curl_multi_remove_handle($mh, $ch[$key]);
}
curl_multi_close($mh)

Я написал приведенный выше код, но он дает мне нули в качестве вывода. любая помощь будет оценена.


person Faaeq    schedule 28.02.2020    source источник


Ответы (1)


curl_errno() не возвращает результирующий код, если он используется внутри curl_multi.

Кажется, это недокументировано, но если ошибка возникает внутри curl_multi(), то resources не будет иметь результирующего кода ошибки, пока не будет вызван curl_multi_info_read(). Есть ссылка на ошибку/запрос документации: https://bugs.php.net/bug.php?id=79318&thanks=4

Оригинальный ответ

Обычно, когда я вмешиваюсь в код ответа 0, у меня возникает локальная проблема (dns, сеть, ssl, url..).

Чтобы копнуть дальше, вы можете проверить, была ли у curl ошибка при выполнении. Это можно проверить с помощью curl_errno(), которая возвращает номер ошибки curl и curl_error(), который вернет описательную строку ошибки.

Код ошибки и сообщение об ошибке, возможно, будут одними из тех, которые вы можете найти здесь: https://curl.haxx.se/libcurl/c/libcurl-errors.html

РЕДАКТИРОВАНИЕ №2

Если вы работаете с curl_multi, вам нужно вызвать curl_multi_info_read() один раз, чтобы получить результирующие коды. Ниже приведен пример того, как вы можете получить соответствующую запись результата.

// your code...

do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);

while ($result = curl_multi_info_read($mh)) {
    if ($result['result'] == CURLM_OK) {
        echo 'Success: ' . curl_getinfo($result['handle'], CURLINFO_HTTP_CODE) . "\n";
    } else {
        echo 'Error: ' . curl_strerror($result['result']) . "\n";
    }
}

Настоящий тест теперь приведет к следующему:

$ php test.php 
Error: Couldn't resolve host name
Success: 200
Success: 200

ИЗМЕНИТЬ №3

Кроме того, кажется, что вызов curl_multi_info_read($mh) также помогает и заполняет внутреннюю информацию в ваши существующие дескрипторы/ресурсы.

На мой взгляд, это немного заблуждение. Я создам отчет об ошибке/документации для php, так как ничего не могу найти об этом. Я просто наткнулся, когда проверял, как жрет его низкоуровневая реализация.

// your code...

do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);

while ($result = curl_multi_info_read($mh)) {}

foreach($ch as $handle) {
    echo "Handle: " . curl_errno($handle) . PHP_EOL;
}
person Christoph Kluge    schedule 28.02.2020
comment
я воспользовался вашим предложением. Успех: 0 Успех: 0 Успех: 0 Успех: 0 Успех: 0 Успех: 0 вот результат, который я получаю. он не выдает ошибку, вместо этого возвращает 0 в качестве кода состояния. - person Faaeq; 28.02.2020
comment
@Faaeq, извиняюсь. Мой первый ответ был совершенно неправильным (я проверял только случай успеха). Кажется, что curl_multi() ведет себя по-другому и не передает ошибку своим дескрипторам, но есть другой путь через curl_multi_info_read(), который вернет curl_errno(). Пожалуйста, дайте мне знать, если это поможет вам сейчас. - person Christoph Kluge; 28.02.2020
comment
Спасибо за ответ. я воспользовался вашим предложением. сделал vardump перед передачей URL-адресов, и я получаю эти результаты, хотя я подключен к Интернету. и эти ссылки работают. ``` C:\wamp64\www\test3.php:11: массив (размер=3) 0 => строка 'google.com' (длина = 17) 1 => строка 'bbc.com' (длина = 14) 2 = › строка 'yahoo.com/nonexistinglink' (длина = 32) Ошибка: не удалось разрешить имя хоста Ошибка: Не удалось разрешить имя хоста Ошибка: не удалось разрешить имя хоста ``` - person Faaeq; 29.02.2020
comment
Можете попробовать добавить протокол? http:// или https:// к URL-адресам? - person Christoph Kluge; 29.02.2020
comment
ссылки имеют http:// в начале. он не отображается здесь, когда я вставляю его по какой-то причине. Я только что сделал тест с https:// тоже. все тот же результат. - person Faaeq; 29.02.2020
comment
Интересно. Можете ли вы попытаться установить CURLOPT_DNS_CACHE_TIMEOUT на 0, чтобы принудительно выполнить новый поиск DNS? Может он кешируется? Я думаю, обычный ping google.com работает? - person Christoph Kluge; 29.02.2020
comment
Я обнаружил проблему, потому что я сижу за прокси, поэтому добавление curl_setopt($ch[$key],CURLOPT_PROXY, '192.168.43.1:7000'); решило эту проблему. но я просто получаю результат для первого URL-адреса и ничего для остальных URL-адресов. - person Faaeq; 29.02.2020
comment
@Faaeq, можете ли вы добавить свою последнюю версию примера кода к своему вопросу? - person Christoph Kluge; 29.02.2020