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://www.example.com',
    'http://www.example.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://www.baidu.com/s?wd=etao_'.$i;
    $urls[] = 'http://www.so.com/s?q=etao_'.$i;
    $urls[] = 'http://www.soso.com/q?w=etao_'.$i;
}
curl($urls, "deal"); 

演示网址 http://demo.bo56.com/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方法比较耗时的话,那整体会非常耗时。

时间: 2024-11-01 11:07:52

php实现并发处理之curl篇的相关文章

【C/S通信交互之HTTP篇】COCOS2DX(CLIENT)使用CURL与JETTY(SERVER)实现手机网游HTTP通信框架(内含解决CURL.H头文件找不到问题)

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2dx/870.html 之前已经分享过一篇基于Cocos2dx与服务器使用Socket进行通信的框架,还不太熟悉的请移步到如下博文中: [C/S通信交互之Socket篇]Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架! 那么今天Himi来分享如何在cocos2dx中

php使用curl简单抓取远程url的方法

 这篇文章主要介绍了php使用curl简单抓取远程url的方法,涉及php操作curl的技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例讲述了php使用curl抓取远程url的方法.分享给大家供大家参考.具体如下: cURL是一个非常有用的php库,可以用来连接不通类型的服务器和协议,下面是一个最基本的范例用来抓取远程网页 ? 1 2 3 4 5 6 <?php $c = curl_init('http://www.w3mentor.com/robots.txt'); curl

PHP curl使用实例

  这篇文章主要介绍了PHP curl使用实例,本文直接给出一个实例,演示直接输出到浏览器和不直接输出到浏览器的不同写法,需要的朋友可以参考下 概述 本博客的前面两篇文章:curl和libcurl简介以及PHP中使用curl对PHP中curl的使用做了简单介绍,但是PHP中curl的使用却并不简单,尤其是curl的各种配置项,本篇文章会讲解几个PHP的实例,以便大家更好的理解curl. 实例:抓取页面 使用curl抓取页面相对来说比较简单,但是这里有一点需要注意的是,curl默认会将抓取的页面直

php中的curl使用入门教程和常见用法实例

[目录] php中的curl使用入门教程和常见用法实例 一.curl的优势 二.curl的简单使用步骤 三.错误处理 四.获取curl请求的具体信息 五.使用curl发送post请求 六.文件上传 七.文件下载 八.http 验证 九.通过代理发送请求 十.发送json数据 十一.cURL批处理(multi cURL) 十二.总结 起先cURL是做为一种命令行工具设计出来的,比较幸运的是,php也支持cURL了.通过cURL这个利器,我们能在php程序中自由地发送 HTTP请求到某个url来获取

【CURL (LIBCURL) 开发 之一】COCOS2DX之LIBCURL(CURL_EASY)的编程教程(帮助手册)!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/curl-libcurl/878.html      注意:如果你的服务器是Java的,那么要注意数据之间的大端小端的处理:否则无法正常获取正确的数据! 本篇介绍使用libcurl编程的一般原则和一些基本方法.本文主要是介绍 c 语言的调用接口,同时也可能很好的适用于其他类 c 语言的接口. 跨平台的可移植代码 libcurl库背后的开发人员

关于php curl获取301或302转向的网址问题的解决方法

在使用php的curl获取远程文件,代码如下: 复制代码 代码如下: <? $ghurl = isset($_GET["id"]) ? $_GET["id"]:"http://www.baidu.com/"; // php 获取 function getContents($url){ $header = array("Referer: http://www.baidu.com/"); $ch = curl_init();

在PHP中使用curl

复制代码 代码如下: $ch = curl_init(); $c_url = 'http://www.baidu.com'; $c_url_data = "product_&type=".$type.""; curl_setopt($ch, CURLOPT_URL,$c_url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_s

php的curl获取有301/302跳转文件出错问题解决

在使用php的curl获取远程文件,代码如下: <? $ghurl = isset($_GET["id"]) ? $_GET["id"]:"http://www.baidu.com/"; // php 获取 function getContents($url){ $header = array("Referer: http://www.baidu.com/"); $ch = curl_init(); curl_setop

不登陆简单设置无线路由实战篇

上期我们为大家介绍了使用命令行指令来设置无线路由器的重要性和应用场所,另外还介绍了名为CURL的小工具,通过他可以实现在命令行下对HTML语言信息的传输,可以显示出某地址全部页面内容,并且和该页面参数进行交互传递.今天就请大家跟着我一起找出无线路由器中的各个参数对应的变量名并通过CURL在命令行中实现对该变量数值的修改,从而完成不登录管理界面也能设置无线路由器的工作. 一.安装httplook寻找变量名 正如上篇文章和本篇开头所说,无线路由器中的各个设置都是与一个个变量名相对应的,也就是说我们修