php

位置:IT落伍者 >> php >> 浏览文章

解析php中curl


发布日期:2024年04月03日
 
解析php中curl
php的multi_curl功能慎用因为某些版本的curl和php的搭配有Bug所以你调试过没问题的代码很可能在别的机器上不正确

相信许多人对php手册中语焉不详的curl_multi一族的函数头疼不已它们文档少给的例子 更是简单的让你无从借鑒我也曾经找了许多网页都没见一个完整的应用例子
•curl_multi_add_handle
•curl_multi_close
•curl_multi_exec
•curl_multi_getcontent
•curl_multi_info_read
•curl_multi_init
•curl_multi_remove_handle
•curl_multi_select
一般来说想到要用这些函数时目的显然应该是要同时请求多个url而不是一个一个依次请求否则不如自己循环去调curl_exec好了

步骤总结如下
第一步调用curl_multi_init
第二步循环调用curl_multi_add_handle
这一步需要注意的是curl_multi_add_handle的第二个参数是由curl_init而来的子handle
第三步持续调用curl_multi_exec
第四步根据需要循环调用curl_multi_getcontent获取结果
第五步调用curl_multi_remove_handle并为每个字handle调用curl_close
第六步调用curl_multi_close

这里有一个网上找的简单例子其作者称为dirty的例子(稍后我会说明为何dirty)

复制代码 代码如下:
*
Heres a quick and dirty example for curlmulti from PHP tested on PHP RC CLI / FreeBSD
*/

$connomains = array(
"
"
"
);

$mh = curl_multi_init();

foreach ($connomains as $i => $url) {
$conn[$i]=curl_init($url);
curl_setopt($conn[$i]CURLOPT_RETURNTRANSFER);
curl_multi_add_handle ($mh$conn[$i]);
}

do { $n=curl_multi_exec($mh$active); } while ($active);

foreach ($connomains as $i => $url) {
$res[$i]=curl_multi_getcontent($conn[$i]);
curl_close($conn[$i]);
}

print_r($res);


整个使用过程差不多就是这样但是这个简单代码有个致命弱点就是在do循环的那段在整个url请求期间是个死循环它会轻易导致CPU占用%

现在我们来改进它这里要用到一个几乎没有任何文档的函数curl_multi_select了虽然C的curl库对select有说明但是php里的接口和用法确与C中有不同

把上面do的那段改成下面这样

复制代码 代码如下:
do {
$mrc = curl_multi_exec($mh$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != ) {
do {
$mrc = curl_multi_exec($mh $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}


因 为$active要等全部url数据接受完毕才变成false所以这里用到了curl_multi_exec的返回值判断是否还有数据当有数据的时候 就不停调用curl_multi_exec暂时没有数据就进入select阶段新数据一来就可以被唤醒继续执行这里的好处就是CPU的无谓消耗没有 了

另外还有一些细节的地方可能有时候要遇到
控制每一个请求的超时时间在curl_multi_add_handle之前通过curl_setopt去做
curl_setopt($ch CURLOPT_TIMEOUT $timeout);

判断是否超时了或者其他错误在curl_multi_getcontent之前用curl_error($conn[$i]);

注意php的multi_curl功能慎用因为某些版本的curl和php的搭配有Bug所以你调试过没问题的代码很可能在别的机器上不正确

例如今天我发现在php搭配curl/版本如果CURLOPT_USERAGENT属性设置成某些值则实际发送的HTTP头的会变成一串二进制值

而恰好这个版本的php中strip_tags函数对含二进制的数据处理的不好这才发现了这个Bug

               

上一篇:PHP中使用协同程序实现合作多任务

下一篇:PHP将汉字转换拼音