php curl批处理实现可控并发异步操作示例
本文实例讲述了phpcurl批处理实现可控并发异步操作。分享给大家供大家参考,具体如下:
通常情况下PHP中的cURL是阻塞运行的,就是说创建一个cURL请求以后必须等它执行成功或者超时才会执行下一个请求:API接口访问一般会首选CURL
在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中,通常需要从第3方网站或者API接口获取数据,在需要处理1个URL队列时,为了提高性能,可以采用cURL提供的curl_multi_*族函数实现简单的并发.
'; print_r($response); echo'
'.date("Y-m-dH:i:s").'
'; echo'
'.str_repeat("-",100).'
'; } $USER_COOKIE=(!empty($_REQUEST['cookie']))?$_REQUEST['cookie']:file_get_contents("cookie.txt"); $curl=newCurl("callback"); $data=array( array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=qmr&type=rec_gametime&referfrom=&rt=0.42521539455332336',//秦美人 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=qmr&fenQuNum=3", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=sq&type=rec_gametime&referfrom=&rt=0.42521539455332336',//神曲 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=sq&fenQuNum=41", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=frxz&type=rec_gametime&referfrom=&rt=0.42521539455332336',//凡人修真 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=frxz&fenQuNum=3", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=smxj&type=rec_gametime&referfrom=&rt=0.42521539455332336',//神魔仙界 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=smxj&fenQuNum=2", CURLOPT_COOKIE=>$USER_COOKIE, ) ), array( 'url'=>'http://dyactive2.vip.xunlei.com/com_sign/?game=qsqy&type=rec_gametime&referfrom=&rt=0.42521539455332336',//倾世情缘 'method'=>'POST', 'post_data'=>'', 'header'=>null, 'options'=>array( CURLOPT_REFERER=>"http://niu.xunlei.com/entergame/?gameNo=qsqy&fenQuNum=11", CURLOPT_COOKIE=>$USER_COOKIE, ) ), ); foreach($dataas$val){ $request=newCurl_request($val['url'],$val['method'],$val['post_data'],$val['header'],$val['options']); $curl->add($request); } $curl->execute(); echo$curl->display_errors();
使用下来效果很好,没有副作用,并发数可控,应用之处多多,自己发挥想象吧
*@linkhttp://t.qq.com/JustPzy
*/
/**
*单一的请求对象
*/
classCurl_request{
public$url='';
public$method='GET';
public$post_data=null;
public$headers=null;
public$options=null;
/**
*
*@paramstring$url
*@paramstring$method
*@paramstring$post_data
*@paramstring$headers
*@paramarray$options
*@returnvoid
*/
publicfunction__construct($url,$method='GET',$post_data=null,$headers=null,$options=null){
$this->url=$url;
$this->method=strtoupper($method);
$this->post_data=$post_data;
$this->headers=$headers;
$this->options=$options;
}
/**
*@returnvoid
*/
publicfunction__destruct(){
unset($this->url,$this->method,$this->post_data,$this->headers,$this->options);
}
}
/**
*包含请求列队处理
*/
classCurl{
/**
*请求url个数
*@varint
*/
private$size=5;
/**
*等待所有cURL批处理中的活动连接等待响应时间
*@varint
*/
private$timeout=5;
/**
*完成请求回调函数
*@varstring
*/
private$callback=null;
/**
*cRUL配置
*@vararray
*/
private$options=array(CURLOPT_SSL_VERIFYPEER=>0,CURLOPT_RETURNTRANSFER=>1,CURLOPT_CONNECTTIMEOUT=>30);
/**
*请求头
*@vararray
*/
private$headers=array();
/**
*请求列队
*@vararray
*/
private$requests=array();
/**
*请求列队索引
*@vararray
*/
private$request_map=array();
/**
*错误
*@vararray
*/
private$errors=array();
/**
*@accesspublic
*@paramstring$callback回调函数
*该函数有4个参数($response,$info,$error,$request)
*$responseurl返回的body
*$infocURL连接资源句柄的信息
*$error错误
*$request请求对象
*/
publicfunction__construct($callback=null){
$this->callback=$callback;
}
/**
*添加一个请求对象到列队
*@accesspublic
*@paramobject$request
*@returnboolean
*/
publicfunctionadd($request){
$this->requests[]=$request;
returnTRUE;
}
/**
*创建一个请求对象并添加到列队
*@accesspublic
*@paramstring$url
*@paramstring$method
*@paramstring$post_data
*@paramstring$headers
*@paramarray$options
*@returnboolean
*/
publicfunctionrequest($url,$method='GET',$post_data=null,$headers=null,$options=null){
$this->requests[]=newCurl_request($url,$method,$post_data,$headers,$options);
returnTRUE;
}
/**
*创建GET请求对象
*@accesspublic
*@paramstring$url
*@paramstring$headers
*@paramarray$options
*@returnboolean
*/
publicfunctionget($url,$headers=null,$options=null){
return$this->request($url,"GET",null,$headers,$options);
}
/**
*创建一个POST请求对象
*@accesspublic
*@paramstring$url
*@paramstring$post_data
*@paramstring$headers
*@paramarray$options
*@returnboolean
*/
publicfunctionpost($url,$post_data=null,$headers=null,$options=null){
return$this->request($url,"POST",$post_data,$headers,$options);
}
/**
*执行cURL
*@accesspublic
*@paramint$size最大连接数
*@returnAmbigous|boolean
*/
publicfunctionexecute($size=null){
if(sizeof($this->requests)==1){
return$this->single_curl();
}else{
return$this->rolling_curl($size);
}
}
/**
*单个url请求
*@accessprivate
*@returnmixed|boolean
*/
privatefunctionsingle_curl(){
$ch=curl_init();
$request=array_shift($this->requests);
$options=$this->get_options($request);
curl_setopt_array($ch,$options);
$output=curl_exec($ch);
$info=curl_getinfo($ch);
//it'snotneccesarytosetacallbackforone-offrequests
if($this->callback){
$callback=$this->callback;
if(is_callable($this->callback)){
call_user_func($callback,$output,$info,$request);
}
}else
return$output;
returntrue;
}
/**
*多个url请求
*@accessprivate
*@paramint$size最大连接数
*@returnboolean
*/
privatefunctionrolling_curl($size=null){
if($size)
$this->size=$size;
else
$this->size=count($this->requests);
if(sizeof($this->requests)<$this->size)
$this->size=sizeof($this->requests);
if($this->size<2)
$this->set_error('sizemustbegreaterthan1');
$master=curl_multi_init();
//添加cURL连接资源句柄到map索引
for($i=0;$i<$this->size;$i++){
$ch=curl_init();
$options=$this->get_options($this->requests[$i]);
curl_setopt_array($ch,$options);
curl_multi_add_handle($master,$ch);
$key=(string)$ch;
$this->request_map[$key]=$i;
}
$active=$done=null;
do{
while(($execrun=curl_multi_exec($master,$active))==CURLM_CALL_MULTI_PERFORM)
;
if($execrun!=CURLM_OK)
break;
//有一个请求完成则回调
while($done=curl_multi_info_read($master)){
//$done完成的请求句柄
$info=curl_getinfo($done['handle']);//
$output=curl_multi_getcontent($done['handle']);//
$error=curl_error($done['handle']);//
$this->set_error($error);
//调用回调函数,如果存在的话
$callback=$this->callback;
if(is_callable($callback)){
$key=(string)$done['handle'];
$request=$this->requests[$this->request_map[$key]];
unset($this->request_map[$key]);
call_user_func($callback,$output,$info,$error,$request);
}
curl_close($done['handle']);
//从列队中移除已经完成的request
curl_multi_remove_handle($master,$done['handle']);
}
//等待所有cURL批处理中的活动连接
if($active)
curl_multi_select($master,$this->timeout);
}while($active);
//完成关闭
curl_multi_close($master);
returntrue;
}
/**
*获取没得请求对象的cURL配置
*@accessprivate
*@paramobject$request
*@returnarray
*/
privatefunctionget_options($request){
$options=$this->__get('options');
if(ini_get('safe_mode')=='Off'||!ini_get('safe_mode')){
$options[CURLOPT_FOLLOWLOCATION]=1;
$options[CURLOPT_MAXREDIRS]=5;
}
$headers=$this->__get('headers');
if($request->options){
$options=$request->options+$options;
}
$options[CURLOPT_URL]=$request->url;
if($request->post_data&&strtolower($request->method)=='post'){
$options[CURLOPT_POST]=1;
$options[CURLOPT_POSTFIELDS]=$request->post_data;
}
if($headers){
$options[CURLOPT_HEADER]=0;
$options[CURLOPT_HTTPHEADER]=$headers;
}
return$options;
}
/**
*设置错误信息
*@accesspublic
*@paramstring$msg
*/
publicfunctionset_error($msg){
if(!empty($msg))
$this->errors[]=$msg;
}
/**
*获取错误信息
*@accesspublic
*@paramstring$open
*@paramstring$close
*@returnstring
*/
publicfunctiondisplay_errors($open='',$close='
'){
$str='';
foreach($this->errorsas$val){
$str.=$open.$val.$close;
}
return$str;
}
/**
*@accesspublic
*@paramstring$name
*@paramstring$value
*@returnboolean
*/
publicfunction__set($name,$value){
if($name=='options'||$name=='headers'){
$this->{$name}=$value+$this->{$name};
}else{
$this->{$name}=$value;
}
returnTRUE;
}
/**
*
*@paramstring$name
*@returnmixed
*@accesspublic
*/
publicfunction__get($name){
return(isset($this->{$name}))?$this->{$name}:null;
}
/**
*@returnvoid
*@accesspublic
*/
publicfunction__destruct(){
unset($this->size,$this->timeout,$this->callback,$this->options,$this->headers,$this->requests,$this->request_map,$this->errors);
}
}
//ENDCurlClass
/*Endoffilecurl.class.php*/
更多关于PHP相关内容感兴趣的读者可查看本站专题:《phpcurl用法总结》、《PHP网络编程技巧总结》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《PHP数据结构与算法教程》、《php程序设计算法总结》、《PHP运算与运算符用法总结》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。