在PHP中检测cURL超时

时间:2014-05-12 15:19:45

标签: php curl

我试图检测cURL请求何时超时。如果这有所不同,我使用curl_multi_exec吗?

curl_errno()的输出为0,表明它是成功的。但是curl_error()的输出是:

  

操作在1435毫秒后超时,0个-1个字节   接收

任何想法为什么错误代码是好的,但错误信息存在?对于超时,我希望错误代码为28。

另外,有什么我可以在curl_getinfo()中检查超时吗?

我使用PHP 5.4.4 / cURL 7.24.0。

编辑1 - 示例代码:

$mh = curl_multi_init();
curl_multi_add_handle($mh,$a);
curl_multi_add_handle($mh,$b);
curl_multi_add_handle($mh,...);

do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($mh) == -1) usleep(100);
    do { $mrc = curl_multi_exec($mh, $active); }
    while ($mrc == CURLM_CALL_MULTI_PERFORM);
}

2 个答案:

答案 0 :(得分:2)

使用curl_multi_exec()时,您需要使用curl_multi_info_read()来获取特定句柄的错误代码。这是由于PHP在简单和多个接口中与cURL接口的方式,以及如何从cURL的curl_multi_info_read()函数中获取错误代码(参见下面的解释)。

基本上,如果您使用多个句柄,则调用curl_errno()curl_error()不可靠或准确。

请参阅manual

中的此修改示例
<?php

$urls = array(
   "http://www.cnn.com/",
   "http://www.bbc.co.uk/",
   "http://www.yahoo.com/",
   'http://wijgeiwojgieowjg.com/',
   'http://www.example.com/',
);

$infos = array();

$mh = curl_multi_init();

foreach ($urls as $i => $url) {
    $conn[$i] = curl_init($url);
    curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1);

    if (strpos($url, 'example.com') !== false) {
        // set a really short timeout for one url
        curl_setopt($conn[$i], CURLOPT_TIMEOUT_MS, 10);
    }

    curl_multi_add_handle($mh, $conn[$i]);
}

do {
    $status = curl_multi_exec($mh, $active);

    if (($info = curl_multi_info_read($mh)) !== false) {
        $infos[$info['handle']] = $info;
    }

} while ($status === CURLM_CALL_MULTI_PERFORM || $active);

foreach ($urls as $i => $url) {
    $info = $infos[$conn[$i]];

    echo "$url returned code {$info['result']}";
    if (version_compare(PHP_VERSION, '5.5.0') >= 0) {
        echo ": " . curl_strerror($info['result']);
    }
    echo "\n";

    if ($info['result'] === 0) {
        $res[$i] = curl_multi_getcontent($conn[$i]);
    }

    curl_close($conn[$i]);
}

输出:

  

http://www.cnn.com/返回代码0

     

http://www.bbc.co.uk/返回代码0

     

http://www.yahoo.com/返回代码0

     

http://wijgeiwojgieowjg.com/返回了代码6

     

http://www.example.com/返回了代码28

<强>解释

具体来说,这是由于PHP curl_exec()调用cURL&#39; curl_easy_perform返回CURLcode(错误代码)并且PHP指定cURL选项CURLOPT_ERRORBUFFER这会导致缓冲区自动填充错误消息(如果发生)。

但是当使用PHP curl_multi_exec()时,PHP会调用cURL&#39; curl_multi_perform,它会立即返回,并且不会返回多句柄的错误代码。您必须调用cURL的curl_multi_info_read函数来获取各个句柄的错误代码。

PHP 5.5.0为cURL的curl_easy_strerror()提供了一个包装器,它返回一个与卷曲错误代码相对应的字符串。

答案 1 :(得分:0)

调试真的很令人沮丧,因为php.net上的文档和示例与异步卷曲相关性很差。

以下是一些示例代码,可帮助演示curl_multi_exec中的DOES工作原理:

// Main work loop

do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while($status = curl_multi_info_read($mh)) {
    if($status['msg'] == CURLMSG_DONE) {

        $errno = $status['result'];
        $errstr = curl_strerror($errno);

        if($errno == CURLE_OK) {

            // This request completed successfully

            // Do something with the info
            $info = curl_getinfo($status['handle');

        } else {

            // There was an error handling this request,
            // like a timeout or something.
            // Note: curl_errno($ch) will probably say success
            // but it's lying to you. Ignore it.

            fwrite(STDERR, "Request failed: Error($errno): $errstr\n");

        }
    }
}

通过上面的主要工作循环,您可以根据需要多次调用它。像

这样的东西
while($this->workRemaining()) {
    $this->work();
    usleep(100); // Sleep, or better yet do something productive
}

我不打算打印全班。你可以做它想做的事。

重要的是检查$status['result']以确定是否有错误。永远不要依赖curl_getinfo($ch),因为它在multi_curl环境中是错误的。