неблокирующие запросы с php и curl не работают со сном - PullRequest
2 голосов
/ 25 октября 2009

Я настроил небольшой скрипт для использования известной функции cUrl кода curl_multi_ * для предоставления асинхронных неблокирующих запросов, это грубая версия кода:

$mch = curl_multi_init();
$ch = curl_init();

url_setopt($ch, CURLOPT_URL,         $url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);          

curl_multi_add_handle($mch ,$ch);
$running = null;
do {
    curl_multi_exec($mch ,$running);
} while($running > 0);

curl_multi_remove_handle($mch,$ch);
curl_close($ch);

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

Прежде всего, я не понимаю, зачем мне нужен цикл while, не сработает ли один раз вызов multi_exec для одного запроса? поскольку неиспользование цикла не запускает скрипт на $ url (я проверял).

во-вторых, и моя самая большая проблема, это должно быть асинхронно, я попытался поместить sleep (10) в другой скрипт, и вызывающий скрипт ждет 10 секунд, прежде чем продолжить, я не понимаю, это должно быть неблокирующим и должно продолжаться.

что я делаю не так?

Ответы [ 2 ]

4 голосов
/ 29 октября 2009

Давайте начнем с конца.

Когда ваш PHP заканчивает выполнение вашего скрипта, он выполняет очистку и убивает все еще работающие ручки curl. Важно помнить это.

Теперь каждый запрос скручивания разделен на несколько этапов, таких как инициализация соединения, подключение, запись данных, чтение данных, закрытие соединения. Средние шаги могут повторяться. И я уверен, что на самом деле за кулисами происходят более сложные вещи, но в целом это описание должно быть правильным.

curl_multi_exec дает управление каждому из дескрипторов в мульти дескрипторе и позволяет ему выполнить следующий шаг, каким бы он ни был. И тогда функция возвращает.

Это объясняет, почему вы не видите запрос без цикла. Это происходит потому, что ваш дескриптор еще не достиг шага, на котором он может выполнить фактическое соединение. Ваш PHP-скрипт завершает работу, выполняет очистку, которая, в свою очередь, убивает дескриптор, у которого вообще не было возможности что-либо сделать.

Итак, теперь ясно, что вам нужно дать ручке шанс что-то сделать. Запуск curl_multi_exec снова и снова является одним из способов достижения этого.

Это объясняет, почему вы испытываете ожидание, эти множественные дескрипторы на самом деле не асинхронны, они просто выглядят так, как они. Ваш цикл дает дескриптору возможность работать, и цикл будет продолжаться до тех пор, пока не завершится запрос (что в вашем примере занимает 10 секунд).

Краткое резюме: вам нужно найти другое решение вашей проблемы (которое заключается в продолжении выполнения другого кода, пока выполняется curl):)

0 голосов
/ 20 ноября 2009

Это хорошо для меня работает:

function get_web_page( $url )
{
$options = array(
    CURLOPT_RETURNTRANSFER => true,     // return web page
    CURLOPT_HEADER         => false,    // don't return headers
    CURLOPT_FOLLOWLOCATION => true,     // follow redirects
    CURLOPT_ENCODING       => "",       // handle all encodings
    CURLOPT_USERAGENT      => "spider", // who am i
    CURLOPT_AUTOREFERER    => true,     // set referer on redirect
    CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
    CURLOPT_TIMEOUT        => 120,      // timeout on response
    CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects
);

$ch      = curl_init( $url );
curl_setopt_array( $ch, $options );
$content = curl_exec( $ch );
$err     = curl_errno( $ch );
$errmsg  = curl_error( $ch );
$header  = curl_getinfo( $ch );
curl_close( $ch );

$header['errno']   = $err;
$header['errmsg']  = $errmsg;
$header['content'] = $content;
return $header;
}

Как функцию вы можете вызывать ее снова и снова. (как асинхронные потоки) Так что на самом деле все, что вам нужно сделать, это написать цикл while для обработки получения и обработки всех полученных завитков ... как только это будет сделано, ваш скрипт может завершиться, избегая остановки в конце проблемы с кодом.

Еще один момент ... вам не нужно форматировать циклы while, как это ..

do { ... } while (conditional)

Вы можете просто использовать:

while (conditional) { ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...