解析php中curl_multi的应用


Posted in PHP onJuly 17, 2013

相信许多人对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):

*
Here's a quick and dirty example for curl-multi from PHP, tested on PHP 5.0.0RC1 CLI / FreeBSD 5.2.1
*/
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
     $conn[$i]=curl_init($url);
      curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
      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占用100%。

现在我们来改进它,这里要用到一个几乎没有任何文档的函数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) != -1) {
                                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。所以你调试过没问题的代码很可能在别的机器上不正确。

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

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

PHP 相关文章推荐
PHP+Mysql+jQuery实现动态展示信息
Oct 08 PHP
PHP对象Object的概念 介绍
Jun 14 PHP
PHP Class&Object -- 解析PHP实现二叉树
Jun 25 PHP
浅析PHP的ASCII码转换类
Jul 05 PHP
PHP header()函数常用方法总结
Apr 11 PHP
在win7中搭建Linux+PHP 开发环境
Oct 08 PHP
php从memcache读取数据再批量写入mysql的方法
Dec 29 PHP
PHP永久登录、记住我功能实现方法和安全做法
Apr 27 PHP
PHP处理postfix邮件内容的方法
Jun 16 PHP
php实现的日历程序
Jun 18 PHP
PHP 多任务秒级定时器的实现方法
May 13 PHP
php判断IP地址是否在多个IP段内
Aug 18 PHP
php curl获取网页内容(IPV6下超时)的解决办法
Jul 16 #PHP
ie与session丢失(新窗口cookie丢失)实测及解决方案
Jul 15 #PHP
实测在class的function中include的文件中非php的global全局环境
Jul 15 #PHP
Php output buffering缓存及程序缓存深入解析
Jul 15 #PHP
PHP 转义使用详解
Jul 15 #PHP
thinkphp 一个页面使用2次分页的实现方法
Jul 15 #PHP
shell脚本作为保证PHP脚本不挂掉的守护进程实例分享
Jul 15 #PHP
You might like
PHP中MD5函数使用实例代码
2008/06/07 PHP
Ajax+PHP 边学边练之四 表单
2009/11/27 PHP
PHP获取时间排除周六、周日的两个方法
2014/06/30 PHP
php str_replace替换指定次数的方法详解
2017/05/05 PHP
服务端 VBScript 与 JScript 几个相同特性的写法 By shawl.qiu
2007/03/06 Javascript
js判断FCKeditor内容是否为空的两种形式
2013/05/14 Javascript
js实现动态添加、删除行、onkeyup表格求和示例
2013/08/18 Javascript
js通过更改按钮的显示样式实现按钮的滑动效果
2014/04/23 Javascript
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
Angular2+如何去除url中的#号详解
2017/12/20 Javascript
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
深入理解react-router 路由的实现原理
2018/09/26 Javascript
JavaScript ES 模块的使用
2020/11/12 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
微信小程序input抖动问题的修复方法
2021/03/03 Javascript
Python 正则表达式的高级用法
2016/12/04 Python
基于python 处理中文路径的终极解决方法
2018/04/12 Python
Python DataFrame 设置输出不显示index(索引)值的方法
2018/06/07 Python
在PyCharm中批量查找及替换的方法
2019/01/20 Python
找Python安装目录,设置环境路径以及在命令行运行python脚本实例
2020/03/09 Python
使用python matploblib库绘制准确率,损失率折线图
2020/06/16 Python
Pytorch 高效使用GPU的操作
2020/06/27 Python
django表单中的按钮获取数据的实例分析
2020/07/31 Python
Python基于Webhook实现github自动化部署
2020/11/28 Python
纯CSS实现设置半个字符的样式
2014/07/03 HTML / CSS
乐天旅游香港网站:日本饭店预订
2017/11/29 全球购物
Farfetch美国:奢侈品牌时尚购物平台
2019/05/02 全球购物
在C语言中"指针和数组等价"到底是什么意思?
2014/03/24 面试题
硅酸盐工业控制专业应届生求职信
2013/11/02 职场文书
财务总监岗位职责
2014/03/07 职场文书
长城英文导游词
2015/01/30 职场文书
欢送会主持词
2015/07/01 职场文书
2016年八一建军节活动总结
2016/04/05 职场文书
致创业的您:这类人不适合餐饮创业
2019/08/19 职场文书
《火纹风花雪月无双》预告“神秘雇佣兵” 紫发剑客
2022/04/13 其他游戏
Nginx报404错误的详细解决方法
2022/07/23 Servers