好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

php实现并发处理之curl篇

php在并发处理方面的确不如java好。但是也有一些方法可以实现并发处理。比如使用curl就可以实现url的并发请求。

看到网上有人说使用curl会导致阻塞,即所有的请求数据都获取完毕后一并返回,然后再进行数据处理。而不是获取一个请求的数据就处理一个数据。其实这种说法是不对的,只能说明他在代码实现上有问题。

在php官方找了段导致阻塞的示例代码,如下:

function multiple_threads_request($nodes){          $mh = curl_multi_init();          $curl_array = array();          foreach($nodes as $i => $url)          {              $curl_array[$i] = curl_init($url);              curl_setopt($curl_array[$i], CURLOPT_RETURNTRANSFER, true);              curl_multi_add_handle($mh, $curl_array[$i]);          }          $running = NULL;          do {              usleep(10000);              curl_multi_exec($mh,$running);          } while($running > 0);                    $res = array();          foreach($nodes as $i => $url)          {              $res[$url] = curl_multi_getcontent($curl_array[$i]);          }                    foreach($nodes as $i => $url){              curl_multi_remove_handle($mh, $curl_array[$i]);          }          curl_multi_close($mh);                 return $res;  }  print_r(muti_thread_request(array(      'http://HdhCmsTestexample测试数据',      'http://HdhCmsTestexample.net',  )));

下面是边请求url,边处理返回数据的示例代码:

/*  * @purpose: 使用curl并行处理url  * @return: array 每个url获取的数据  * @param: $urls array url列表  * @param: $callback string 需要进行内容处理的回调函数。示例:func(array)  */ function curl($urls = array(), $callback = '') {     $response = array();     if (empty($urls)) {         return $response;     }     $chs = curl_multi_init();     $map = array();     foreach($urls as $url){         $ch = curl_init();         curl_setopt($ch, CURLOPT_URL, $url);         curl_setopt($ch, CURLOPT_TIMEOUT, 1);         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);         curl_setopt($ch, CURLOPT_HEADER, 0);         curl_setopt($ch, CURLOPT_NOSIGNAL, true);         curl_multi_add_handle($chs, $ch);         $map[strval($ch)] = $url;     }     do{         if (($status = curl_multi_exec($chs, $active)) != CURLM_CALL_MULTI_PERFORM) {             if ($status != CURLM_OK) { break; } //如果没有准备就绪,就再次调用curl_multi_exec             while ($done = curl_multi_info_read($chs)) {                 $info = curl_getinfo($done["handle"]);                 $error = curl_error($done["handle"]);                 $result = curl_multi_getcontent($done["handle"]);                 $url = $map[strval($done["handle"])];                 $rtn = compact('info', 'error', 'result', 'url');                 if (trim($callback)) {                     $callback($rtn);                 }                 $response[$url] = $rtn;                 curl_multi_remove_handle($chs, $done['handle']);                 curl_close($done['handle']);                 //如果仍然有未处理完毕的句柄,那么就select                 if ($active > 0) {                     curl_multi_select($chs, 0.5); //此处会导致阻塞大概0.5秒。                 }             }         }     }     while($active > 0); //还有句柄处理还在进行中     curl_multi_close($chs);     return $response; }   //使用方法 function deal($data){     if ($data["error"] == '') {         echo $data["url"]." -- ".$data["info"]["http_code"]."\n";     } else {         echo $data["url"]." -- ".$data["error"]."\n";     } } $urls = array(); for ($i = 0; $i < 10; $i++) {     $urls[] = 'http://HdhCmsTestbaidu测试数据/s?wd=etao_'.$i;     $urls[] = 'http://HdhCmsTestso测试数据/s?q=etao_'.$i;     $urls[] = 'http://HdhCmsTestsoso测试数据/q?w=etao_'.$i; } curl($urls, "deal");

演示网址 http://demo.bo56测试数据/bigpipe/

注释:

1.关于curl_multi_exec函数的返回值:

返回CURLM_CALL_MULTI_PERFORM 说明curl_multi_exec需要马上被再调用一次。

返回CURLM_OK 说明已经有需要处理的数据。这时你需要进行相关处理,处理完后再次调用curl_multi_exec。

php中的curl_multi_exec是调用的curl库中的curl_multi_perform方法。代码在multi.c的230行左右。

2.此方式,虽然在获取数据和数据处理上是并行的,但是在数据处理时依然是串行的。即数据是一条条依次处理的。如果deal方法比较耗时的话,那整体会非常耗时。

查看更多关于php实现并发处理之curl篇的详细内容...

  阅读:56次