<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[php function:真正的并发请求,curl_multi,PHP多线程并发]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Fri, 22 Oct 2010 05:05:26 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	c版的curl_multi为php扩展准备<br/><br/><div class="code">#include &lt;stdio.h&gt;<br/>#include &lt;string.h&gt;<br/>/* somewhat unix-specific */<br/>#include &lt;sys/time.h&gt;<br/>#include &lt;unistd.h&gt; <br/>/* curl stuff */<br/>#include &lt;curl/curl.h&gt;<br/>/*<br/>* Simply download two HTTP files!<br/>*/<br/>int main(int argc, char **argv)<br/>&nbsp;&nbsp; &#123;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp; CURL *http_handle;<br/>&nbsp;&nbsp;&nbsp;&nbsp; CURL *http_handle2;<br/>&nbsp;&nbsp;&nbsp;&nbsp; CURLM *multi_handle; <br/>&nbsp;&nbsp;&nbsp;&nbsp; int still_running; /* keep number of running handles */ <br/>&nbsp;&nbsp;&nbsp;&nbsp; http_handle = curl_easy_init();<br/>&nbsp;&nbsp;&nbsp;&nbsp; http_handle2 = curl_easy_init(); <br/>&nbsp;&nbsp;&nbsp;&nbsp;/* set options */<br/>&nbsp;&nbsp;&nbsp;&nbsp; curl_easy_setopt(http_handle, CURLOPT_URL, &quot;http://www.sohu.com/&quot;); <br/>&nbsp;&nbsp;&nbsp;&nbsp;/* set options */<br/>&nbsp;&nbsp;&nbsp;&nbsp;curl_easy_setopt(http_handle2, CURLOPT_URL, &quot;http://www.sina.com.cn/&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp; /* init a multi stack */<br/>&nbsp;&nbsp;&nbsp;&nbsp; multi_handle = curl_multi_init();<br/>&nbsp;&nbsp;&nbsp;&nbsp;/* add the individual transfers */<br/>&nbsp;&nbsp;&nbsp;&nbsp; curl_multi_add_handle(multi_handle, http_handle);<br/>&nbsp;&nbsp;&nbsp;&nbsp; curl_multi_add_handle(multi_handle, http_handle2);<br/>&nbsp;&nbsp;&nbsp;&nbsp; /* we start some action by calling perform right away */<br/>&nbsp;&nbsp;&nbsp;&nbsp;while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &amp;still_running));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(still_running) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct timeval timeout;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int rc; /* select() return code */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd_set fdread;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd_set fdwrite;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fd_set fdexcep;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int maxfd;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FD_ZERO(&amp;fdread);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FD_ZERO(&amp;fdwrite);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FD_ZERO(&amp;fdexcep);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* set a suitable timeout to play around with */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout.tv_sec = 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout.tv_usec = 0; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* get file descriptors from the transfers */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_fdset(multi_handle, &amp;fdread, &amp;fdwrite, &amp;fdexcep, &amp;maxfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* In a real-world program you OF COURSE check the return code of the<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function calls, *and* you make sure that maxfd is bigger than -1 so<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; that the call to select() below makes sense! */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rc = select(maxfd+1, &amp;fdread, &amp;fdwrite, &amp;fdexcep, &amp;timeout);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch(rc) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case -1:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* select error */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 0:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* timeout or readable/writable sockets */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(CURLM_CALL_MULTI_PERFORM ==curl_multi_perform(multi_handle, &amp;still_running));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_cleanup(multi_handle);<br/>&nbsp;&nbsp;&nbsp;&nbsp;curl_easy_cleanup(http_handle);<br/>&nbsp;&nbsp;&nbsp;&nbsp;curl_easy_cleanup(http_handle2);<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;</div><br/><br/>编译的时候会报错<br/><br/><br/><div class="code">gcc curl_mult.cpp -o aa -lcurl</div><br/><br/>需要加上<br/><br/><br/><div class="code">gcc curl_mult.cpp -o aa -lcurl -lstdc++</div><br/><br/>来源：http://hi.baidu.com/lostdays/blog/item/e5f88a22270e61fad7cae2d0.html<br/><br/><br/><br/><br/><br/><br/><br/>这是一个自己写的函数<br/><br/>由于blog位置显示的原因，请点击code的原文<br/><br/>http://www.trackself.com/code/curl_multi.html<br/><br/>关键在于GOOGLE一下：$mh = curl_multi_init();&nbsp;&nbsp; 以curl_multi为关键词则可<br/><br/>程序的好处在于我将日常的需要都写在里面了，而且节约CPU和内存<br/><div class="code">&nbsp;&nbsp;function cmi($connomains,$killspace=TRUE,$forhtml=TRUE,$timeout=6,$header=0,$follow=1)&#123;<br/>&nbsp;&nbsp; /*<br/>&nbsp;&nbsp;&nbsp;&nbsp;cmi该函数的目的在于并发请求多个url，然后返回http://www.trackself.com编写,真正的PHP并发<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原文发表在http://www.trackself.com/archives/463.html<br/>&nbsp;&nbsp;&nbsp;&nbsp;此并发请求在url多于2的时候，明显比for ... file_get_contents ...要优很多<br/>&nbsp;&nbsp;&nbsp;&nbsp;核心是curl库的curl_multi方法<br/>&nbsp;&nbsp;&nbsp;&nbsp;用法：<br/>&nbsp;&nbsp;&nbsp;&nbsp;$urls=array(<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://www.google.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://www.baidu.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://sina.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://163.com&#039;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;$htmls=cmi($urls);<br/>&nbsp;&nbsp;&nbsp;&nbsp;print_r($htmls);<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//传入的$connomains是URL一维数组，由http://www.trackself.com编写<br/>&nbsp;&nbsp;&nbsp;&nbsp;//该函数的目的在于并发请求多个url，然后返回源码<br/>&nbsp;&nbsp;&nbsp;&nbsp;//以一次性略增加CPU为代价<br/>&nbsp;&nbsp;&nbsp;&nbsp;//来减轻服务器因为for ... file_get_contents ...的长时连接负担及内存和CPU的负担，所以并发数不要大多（50以内效果非常好），尽量不要用于单页面或3页面以内的请求&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$killspace为真时表示自动去掉HTML中换行及多余的空白，$forhtml为真时表示反回源码，为faluse时就是并发执行请求了（可以用于计划任务）<br/>&nbsp;&nbsp;&nbsp;&nbsp;//后面的几个参数的详细说明请看注释，毕竟函数不长<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res=array();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$urlsa=array();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$results=array();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mh = curl_multi_init();//创建多curl对象，为了几乎同时执行&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach ($connomains as $i =&gt; $url) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $conn&#91;$i&#93;=curl_init($url);//若url中含有gb2312汉字，例如FTP时，要在传入url的时候处理一下，这里不用<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curl_setopt($conn&#91;$i&#93;, CURLOPT_TIMEOUT, $timeout);//此时间须根据页面的HTML源码出来的时间，一般是在1s内的，慢的话应该也不会6秒，极慢则是在16秒内<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_setopt($conn&#91;$i&#93;, CURLOPT_HEADER, $header);//不返回请求头，只要源码<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_setopt($conn&#91;$i&#93;,CURLOPT_RETURNTRANSFER,1);//必须为1<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curl_setopt($conn&#91;$i&#93;, CURLOPT_FOLLOWLOCATION, $follow);//如果页面含有自动跳转的代码如301或者302HTTP时，自动拿转向的页面<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_add_handle ($mh,$conn&#91;$i&#93;);//关键，一定要放在上面几句之下，将单curl对象赋给多对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//下面一大步的目的是为了减少cpu的无谓负担，暂时不明，来自php.net的建议，几乎是固定用法<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mrc = curl_multi_exec($mh,$active);//当无数据时或请求暂停时，active=true<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ($active and $mrc == CURLM_OK) &#123;//当无数据时或请求暂停时，active=true,为了减少cpu的无谓负担,这一步很难明啊<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (curl_multi_select($mh) != -1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mrc = curl_multi_exec($mh, $active);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; while ($mrc == CURLM_CALL_MULTI_PERFORM);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/////////////////////////////////////////////////////////////////////////////////////////<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//下面返回结果<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach ($connomains as $i =&gt; $url) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$cinfo=curl_getinfo($conn&#91;$i&#93;);//可用于取得一些有用的参数，可以认为是header<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$url=$cinfo&#91;url&#93;;//真实url,有些url<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($killspace)&#123;//有点水消耗<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str=trim(curl_multi_getcontent($conn&#91;$i&#93;));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str = preg_replace(&#039;/&#92;s(?=&#92;s)/&#039;, &#039;&#039;, $str);//去掉跟随别的挤在一块的空白&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str = preg_replace(&#039;/&#91;&#92;n&#92;r&#92;t&#93;/&#039;, &#039; &#039;, $str);&nbsp;&nbsp;//最后，去掉非space 的空白，用一个空格代替<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$i&#93;=stripslashes($str);//取得对象源码，并取消换行，节约内存的同时，可以方便作正则处理<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$i&#93;=curl_multi_getcontent($conn&#91;$i&#93;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!$forhtml)&#123;//节约内存&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$i&#93;=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*下面这一段放一些高消耗的程序代码，用来处理HTML，我保留的一句=NULL是要提醒，及时清空对象释放内存，此程序在并发过程中如果源码太大，内在消耗严重<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //事实上，这里应该做一个callback函数或者你应该将你的逻辑直接放到这里来，我为了程序可重复，没这么做<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preg_match_all($preg,$res&#91;$i&#93;,$matchlinks);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res&#91;$i&#93;=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_close($conn&#91;$i&#93;);//关闭所有对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_remove_handle($mh&nbsp;&nbsp;, $conn&#91;$i&#93;);&nbsp;&nbsp; //用完马上释放资源&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_close($mh);$mh=NULL;$conn=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $res;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;//cmi</div><br/><br/>--------------------------------------------------------------------------------<br/>下面是版本二，几乎一至的代码，但输出的形式改为为带key; <br/>--------------------------------------------------------------------------------<br/><br/><br/><div class="code">function cmi($connomains,$killspace=TRUE,$forhtml=TRUE,$timeout=6,$header=0,$follow=1)&#123;<br/>&nbsp;&nbsp; /*<br/>&nbsp;&nbsp;&nbsp;&nbsp;cmi该函数的目的在于并发请求多个url，然后返回http://www.trackself.com编写,真正的PHP并发<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原文发表在http://www.trackself.com/archives/463.html<br/>&nbsp;&nbsp;&nbsp;&nbsp;此并发请求在url多于2的时候，明显比for ... file_get_contents ...要优很多<br/>&nbsp;&nbsp;&nbsp;&nbsp;核心是curl库的curl_multi方法<br/>&nbsp;&nbsp;&nbsp;&nbsp;用法：<br/>&nbsp;&nbsp;&nbsp;&nbsp;//array_flip(array_flip($connomains))<br/>&nbsp;&nbsp;&nbsp;&nbsp;$urls=array(<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://www.google.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://www.baidu.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://sina.com&#039;,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;http://163.com&#039;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;$urls=array_flip(array_flip($connomains));//去除url中的重复的项，注意传入urls时一定要系合法的url表达，虽然不会影响其它url执行，但会减慢执行速度<br/>&nbsp;&nbsp;&nbsp;&nbsp;$htmls=cmi($urls);<br/>&nbsp;&nbsp;&nbsp;&nbsp;print_r($htmls);<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//传入的$connomains是URL一维数组，由http://www.trackself.com编写<br/>&nbsp;&nbsp;&nbsp;&nbsp;//该函数的目的在于并发请求多个url，然后返回源码<br/>&nbsp;&nbsp;&nbsp;&nbsp;//以一次性略增加CPU为代价<br/>&nbsp;&nbsp;&nbsp;&nbsp;//来减轻服务器因为for ... file_get_contents ...的长时连接负担及内存和CPU的负担，所以并发数不要大多（50以内效果非常好），尽量不要用于单页面或3页面以内的请求&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;//$killspace为真时表示自动去掉HTML中换行及多余的空白，$forhtml为真时表示反回源码，为faluse时就是并发执行请求了（可以用于计划任务）<br/>&nbsp;&nbsp;&nbsp;&nbsp;//后面的几个参数的详细说明请看注释，毕竟函数不长<br/>&nbsp;&nbsp;&nbsp;&nbsp; */<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res=array();//用于保存结果&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;//$connomains=array_flip(array_flip($connomains));//去除url中的重复项<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mh = curl_multi_init();//创建多curl对象，为了几乎同时执行&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach ($connomains as $i =&gt; $url) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $conn&#91;$url&#93;=curl_init($url);//若url中含有gb2312汉字，例如FTP时，要在传入url的时候处理一下，这里不用<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curl_setopt($conn&#91;$url&#93;, CURLOPT_TIMEOUT, $timeout);//此时间须根据页面的HTML源码出来的时间，一般是在1s内的，慢的话应该也不会6秒，极慢则是在16秒内<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_setopt($conn&#91;$url&#93;, CURLOPT_HEADER, $header);//不返回请求头，只要源码<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_setopt($conn&#91;$url&#93;,CURLOPT_RETURNTRANSFER,1);//必须为1<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curl_setopt($conn&#91;$url&#93;, CURLOPT_FOLLOWLOCATION, $follow);//如果页面含有自动跳转的代码如301或者302HTTP时，自动拿转向的页面<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_add_handle ($mh,$conn&#91;$url&#93;);//关键，一定要放在上面几句之下，将单curl对象赋给多对象<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//下面一大步的目的是为了减少cpu的无谓负担，暂时不明，来自php.net的建议，几乎是固定用法<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mrc = curl_multi_exec($mh,$active);//当无数据时或请求暂停时，active=true<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ($active and $mrc == CURLM_OK) &#123;//当无数据时或请求暂停时，active=true,为了减少cpu的无谓负担,这一步很难明啊<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (curl_multi_select($mh) != -1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$mrc = curl_multi_exec($mh, $active);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; while ($mrc == CURLM_CALL_MULTI_PERFORM);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/////////////////////////////////////////////////////////////////////////////////////////<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//下面返回结果<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach ($connomains as $i =&gt; $url) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$cinfo=curl_getinfo($conn&#91;$url&#93;);//可用于取得一些有用的参数，可以认为是header<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//$url=$cinfo&#91;url&#93;;//真实url,有些url<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if($killspace)&#123;//有点水消耗<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str=trim(curl_multi_getcontent($conn&#91;$url&#93;));<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str = preg_replace(&#039;/&#92;s(?=&#92;s)/&#039;, &#039;&#039;, $str);//去掉跟随别的挤在一块的空白&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$str = preg_replace(&#039;/&#91;&#92;n&#92;r&#92;t&#93;/&#039;, &#039; &#039;, $str);&nbsp;&nbsp;//最后，去掉非space 的空白，用一个空格代替<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$url&#93;=stripslashes($str);//取得对象源码，并取消换行，节约内存的同时，可以方便作正则处理<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$url&#93;=curl_multi_getcontent($conn&#91;$url&#93;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!$forhtml)&#123;//节约内存&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$res&#91;$url&#93;=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*下面这一段放一些高消耗的程序代码，用来处理HTML，我保留的一句=NULL是要提醒，及时清空对象释放内存，此程序在并发过程中如果源码太大，内在消耗严重<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //事实上，这里应该做一个callback函数或者你应该将你的逻辑直接放到这里来，我为了程序可重复，没这么做<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; preg_match_all($preg,$res&#91;$i&#93;,$matchlinks);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $res&#91;$i&#93;=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_close($conn&#91;$url&#93;);//关闭所有对象 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_remove_handle($mh&nbsp;&nbsp;, $conn&#91;$url&#93;);&nbsp;&nbsp; //用完马上释放资源&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curl_multi_close($mh);$mh=NULL;$conn=NULL;$connomains=NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $res;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;//cmi</div><br/><br/><br/>
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] php function:真正的并发请求,curl_multi,PHP多线程并发]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>