curl_multi_select
をタイムアウトで使用している場合は、特定の期間、またはすべてのハンドルが一定期間データを受信しなかった場合に、接続を閉じることができるはずです。唯一の問題は、あなたが仕事ができる任意のデータ
$timeout = 45; // abort after 45 seconds with no data
$lastReceived = 0; // time data was last received
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
$lastReceived = time();
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
} else {
if (time() - $lastReceived > $timeout) {
// no data received within timeout
// close cURL handles & multi connection and restart
}
}
}
を受信していないが、あなたが特定のハンドルをきめ細かく制御を見つける与えない扱うかわからないです。
エラーが発生するずっと前にそれらを検出したい状況でタイムアウトを処理した最善の方法は、とCURLOPT_WRITEFUNCTION
を組み合わせて使用しています。
私はコードをマルチインターフェイスに変換しませんが、必要に応じて既存のコードに変換することができます。
考えられるのは、独自のタイムアウトを定義し、ハンドルが最後にデータを受信した日時を記録することです。その時間内にデータが受信されなかった場合は、転送を中止してやり直すことができます。
データを毎秒取得する必要があるため、このタイムラインを早期に検出したいと考えています。すべての種類の接続問題で非常にうまく動作し、テストでは、cURLがエラーアウトするよりもはるかに迅速にタイムアウトが検出されたことがわかりました。 CURLOPT_WRITEFUNCTION
を使用しての
1つの副作用は、あなたがそれは残念ながらそれほど単純ではないのですが、それは動作しますcurl_exec
<?php
$readTimeout = 45; // number of seconds to time out after if no data received
$lastReceived = 0; // time data was last received on the handle
$buffer = ''; // buffer for storing response (you'll need one for each handle)
//...when initializing cURL
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progressFunction');
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'writeFunction');
// don't set anything for CURLOPT_RETURNTRANSFER
$result = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_errno($ch);
// $result will be false on any failure or timeout
// check $info['http_code'] for HTTP response status
// $error will be empty if no error occurred
// on success, $buffer will contain the full response body
// if failed, you can try reconnecting and resending the request until successful
//...
function writeFunction($handle, $data)
{
global $lastReceived, $buffer; // <-- I use class properties instead
$lastReceived = time();
$size = strlen($data);
$buffer .= $data;
return $size;
}
function progressFunction($ch, $dltotal, $dlnow, $ultotal, $ulnow)
{
global $lastReceived, $readTimeout;
$time = time();
if ($time - $lastReceived > $readTimeout) {
// set error state - no data received within timeout
return 1; // non-zero causes cURL to disconnect
}
return 0;
}
からデータを取得するためにCURLOPT_RETURNTRANSFER
を使用し、それが読んだとしてデータを保存する必要はないだろうということですあなたがしたいことをうまくやっています。希望が役立ちます。
私がタイムアウトに持っている最大の問題は、接続が終了することです。時間の範囲内でダウンロードサイズを追跡する提案された方法は、完全に機能します。詳細な回答を書く時間をとってくれてありがとう。 – Twifty
あなたが助けてくれることを歓迎します。私のユースケースはきわめて明確で、progressFunctionとwriteFunctionの両方に他のコードを用意していました。拡張するために、connect/requestロジックは基本的に永遠に実行され、タイムアウト/エラーの後で再接続する無限ループ内に存在します(progressFunctionまたはcURLから強制的に強制されます)。 – drew010