但在 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."; }
沒有留言:
張貼留言