当我检查10个url时,如果能够与主机服务器建立连接,则句柄将返回成功消息(CURLE_OK)。
在处理每个句柄时,如果服务器拒绝连接,则句柄将包含错误消息。
问题是,我认为当我们得到一个坏的句柄时,CURL会标记这个句柄但继续处理未处理的句柄,然而事实并非如此。当我们遇到坏的句柄时,CURL会将该句柄标记为坏的,但不会处理其余未处理的句柄。
如果我与所有句柄都建立连接,这种情况很难被发现,因为大多数情况下都是这样的(CURL仅在第一个坏连接上停止)。
为了测试,我必须找到一个适合加载缓慢/拒绝x数量的同时连接的网站。
在处理每个句柄时,如果服务器拒绝连接,则句柄将包含错误消息。
问题是,我认为当我们得到一个坏的句柄时,CURL会标记这个句柄但继续处理未处理的句柄,然而事实并非如此。当我们遇到坏的句柄时,CURL会将该句柄标记为坏的,但不会处理其余未处理的句柄。
如果我与所有句柄都建立连接,这种情况很难被发现,因为大多数情况下都是这样的(CURL仅在第一个坏连接上停止)。
为了测试,我必须找到一个适合加载缓慢/拒绝x数量的同时连接的网站。
set_time_limit(0);
$l = array(
'http://smotri.com/video/list/',
'http://smotri.com/video/list/sports/',
'http://smotri.com/video/list/animals/',
'http://smotri.com/video/list/travel/',
'http://smotri.com/video/list/hobby/',
'http://smotri.com/video/list/gaming/',
'http://smotri.com/video/list/mult/',
'http://smotri.com/video/list/erotic/',
'http://smotri.com/video/list/auto/',
'http://smotri.com/video/list/humour/',
'http://smotri.com/video/list/film/'
);
$mh = curl_multi_init();
$s = 0;
$f = 10;
while($s <= $f)
{
$ch = curl_init();
$curlsettings = array(
CURLOPT_URL => $l[$s],
CURLOPT_TIMEOUT => 0,
CURLOPT_CONNECTTIMEOUT => 0,
CURLOPT_RETURNTRANSFER => 1
);
curl_setopt_array($ch, $curlsettings);
curl_multi_add_handle($mh,$ch);
$s++;
}
$active = null;
do
{
curl_multi_exec($mh,$active);
curl_multi_select($mh);
$info = curl_multi_info_read($mh);
echo '<pre>';
var_dump($info);
if($info['result'] === CURLE_OK)
echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' success<br>';
if($info['result'] != 0)
echo curl_getinfo($info['handle'],CURLINFO_EFFECTIVE_URL) . ' failed<br>';
} while ($active > 0);
curl_multi_close($mh);
我已经在脚本中转储了$info,询问Multi Handle是否有任何正在处理的句柄上有任何新信息。
当脚本结束时,如果没有新信息可用(句柄仍在处理),我们将看到一些bool(false),并且如果所有操作都成功,则会返回所有句柄,如果一个句柄失败则仅返回有限的句柄。
我无法修复这个问题,可能是我忽视了什么,而且我已经尝试修复一些与此无关的东西。
一些尝试修复的方法如下:
将每个$ch句柄分配给数组-$ch[1]、$ch[2]等(而不是向multi_handle添加当前$ch句柄,然后覆盖-如测试中所述)
成功/失败后删除处理程序
将CURLOPT_CONNECTTIMEOUT和CURLOPT_TIMEOUT设置为无限大。
- 还有很多。(我会在更新帖子时补充)
使用Php版本5.4.14进行测试,希望我已经足够清楚地说明了这些问题。
感谢您的阅读。
curl_multi_exec()
。 我从来没有看到过这样的问题(我已经使用它每天处理数百万个REST调用)。 你可以随意使用它或查看内部代码以获取灵感。 https://github.com/mikecbrant/php-rest-client/blob/master/rest_client.class.php - Mike BrantCURLE_OK
是一个预定义常量,而不是一个字符串。因此,你可能需要更改为if (CURLE_OK === $info['result']) then { echo 'success'; } else { echo 'failure';}
。 - Max