但在 linux 上,若設定 timeout 小於 1 秒,而且系統是使用 standard system name resolver(系統標準的DNS解析) 時,須同時將 CURLOPT_NOSIGNAL 設為 1,才可以正常運作,否則不管執行時間是多少,都會得到執行逾時的錯誤訊息。(但缺點是, DNS 解析將不受逾時限制)
官網 CURLOPT_CONNECTTIMEOUT_MS 選項的說明
http://www.php.net/manual/en/function.curl-setopt.php
The number of milliseconds to wait while trying to connect. Use 0 to wait indefinitely. If libcurl is built to use the standard system name resolver, that portion of the connect will still use full-second resolution for timeouts with a minimum timeout allowed of one second.
原因可以參考 风雪之隅:Curl的毫秒超时的一个”Bug”,有詳細的說明。
在 PHP 官網也有這個問題的相關討論
http://www.php.net/manual/en/function.curl-setopt.php#104597
以下用官網上面的範例,稍微修改,做個測試。
測試 1:
將 CURLOPT_NOSIGNAL 設為 0,或沒設定,curl 執行結果總是 timeout。
測試網頁:http://demo.cinc.biz/curl_test_timeout/nosignal-0.php
執行結果總是 "cURL Error (28): Timeout was reached"
<?php
if (!isset($_GET['foo'])) {
// Client
$ch = curl_init('http://demo.cinc.biz/curl_test_timeout/nosignal-0.php?foo=bar');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOSIGNAL, 0); // CURLOPT_NOSIGNAL 設為 0
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 900); // 設定最長執行 900 毫秒
$data = curl_exec($ch);
$curl_errno = curl_errno($ch);
$curl_error = curl_error($ch);
curl_close($ch);
if ($curl_errno > 0) {
echo "cURL Error ($curl_errno): $curl_error\n";
} else {
echo "Data received: $data\n";
}
} else {
// Server
// sleep(10);
echo "Done.";
}
測試 2:
將 CURLOPT_NOSIGNAL 設為 1
測試網頁:http://demo.cinc.biz/curl_test_timeout/nosignal-1.php
執行結果如果沒逾時,會得到 "Data received: Done. "
<?php
if (!isset($_GET['foo'])) {
// Client
$ch = curl_init('http://demo.cinc.biz/curl_test_timeout/nosignal-1.php?foo=bar');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1); // CURLOPT_NOSIGNAL 設為 1
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 900); // 設定最長執行 900 毫秒
$data = curl_exec($ch);
$curl_errno = curl_errno($ch);
$curl_error = curl_error($ch);
curl_close($ch);
if ($curl_errno > 0) {
echo "cURL Error ($curl_errno): $curl_error\n";
} else {
echo "Data received: $data\n";
}
} else {
// Server
// sleep(10);
echo "Done.";
}
沒有留言:
張貼留言