簡體   English   中英

在PHP中檢測cURL超時

[英]Detect cURL timeout in PHP

我正試圖檢測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);
}

使用curl_multi_exec() ,您需要使用curl_multi_info_read()來獲取特定句柄的錯誤代碼。 這是由於PHP在簡單和多個接口中與cURL接口的方式,以及如何從cURL的curl_multi_info_read()函數在各個句柄上獲取錯誤代碼(請參閱下面的說明)。

基本上,如果您使用多個句柄,則調用curl_errno()curl_error()不可靠或不准確。

請參閱手冊中的此修改示例:

<?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的curl_easy_perform返回CURLcode(錯誤代碼),PHP指定了cURL選項CURLOPT_ERRORBUFFER ,這會導致緩沖區自動填充錯誤消息(如果發生)。

但是當使用PHP的curl_multi_exec() ,PHP會調用cURL的curl_multi_perform ,它會立即返回並且不會返回多句柄的錯誤代碼。 您必須調用cURL的curl_multi_info_read函數來獲取各個句柄的錯誤代碼。

PHP 5.5.0為cURL的curl_easy_strerror()提供了一個包裝器,它返回一個對應於curl錯誤代碼的字符串。

這可能是非常令人沮喪的調試,因為php.net上的文檔和示例與async curl相關性很差。

下面是一些示例代碼,以幫助演示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環境中是錯誤的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM