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