libcurl 中使用curl_multi_perform()函数执行订阅类型url的问题
前提概要
当需要同时处理多个url时,可采用curl_multi_perform方式执行,如下代码1:
//初始化一个multi curl 对象
CURLM * curl_m = curl_multi_init();
CURL * my_curl[CURL_NUM];
char rcvbuf[CURL_NUM][MAXHEADLEN] = { };
//其他初始化代码略过... //执行多个url
while(running_handles)
{
if (- == curl_multi_select(curl_m))
{
printf("curl_multi_select error !\n");
break;
}
else {
// select监听到事件,调用curl_multi_perform通知curl执行相应的操作 //
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles));
}
} //解析数据
int msgs_left;
CURLMsg * curl_msg;
while((curl_msg = curl_multi_info_read(curl_m, &msgs_left)))
{
if (CURLMSG_DONE == curl_msg->msg)
{
int idx;
for (idx = ; idx < CURL_NUM; ++idx)
{
if (curl_msg->easy_handle == my_curl[idx]) break;
} if (idx == CURL_NUM)
{
printf("curl not found !\n" );
}
else
{
printf("\ncurl[%d] rcvbuf:\n%s\n", idx,rcvbuf[idx]);
//数据处理...
}
}
}
问题概要
现在我的url为订阅方式,每个curl都会一直收数据(即使没数据也会每10s收到一帧心跳消息),永远不会退出,即上面的循环永远在执行,这样我无法运行到"解析数据"那一步。所以我需要在循环内判断某个curl是否有新数据到来。
方法1(不行)
首先想到的方法是直接将curl_multi_info_read()函数直接移到循环内,看是否能受到数据,如下代码2:
//执行多个url,并解析数据
while(running_handles)
{
if (- == curl_multi_select(curl_m))
{
printf("curl_multi_select error !\n");
break;
}
else {
// select监听到事件,调用curl_multi_perform通知curl执行相应的操作 //
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles));
//检测哪一个curl[idx]来的数据
while ((curl_msg = curl_multi_info_read(curl_m, &msgs_left)))
{
if (CURLMSG_DONE == curl_msg->msg)
{
int idx;
for (idx = ; idx < CURL_NUM; ++idx)
{
if (curl_msg->easy_handle == my_curl[idx]) break;
}
if (idx == CURL_NUM)
{
printf("curl not found !\n" );
}
else
{
printf("\ncurl[%d] rcvbuf:\n%s\n", idx,rcvbuf[idx]);
//数据处理...
memset(rcvbuf[idx], , sizeof(rcvbuf[idx]));//清空buf下轮循环还要用
}
}
}
}
}
显然是我想多了,这样处理之后唯一的不同就是,哪个curl执行完了就打印哪个的数据(代码1的是只能等到所有的curl都执行完毕退出循环后依次打印rcvbuf[idx]),但我的curl是订阅的,根本执行不完,这样也没法打印,除非rcvbuf[idx]溢出...
方法2(暂时不行)
rcvbuf[idx]溢出?这样肯定不可能,但是让我想起了curl_easy_setopt()函数,这货可以配置curl的各种功能,或许总有一个能满足我吧:
CURLOPT_TIMEOUT_MS 配置超时时间?
不对,这个是要超时了curl直接挂了;
CURLOPT_RANGE 配置断点续传?
貌似可以;通过测试发现收指定XX个字节满了后该curl就退出了,即使后面还有数据他也不要了,这不是我们想看到的。
还有一个接收超时时间的配置?
同上,超过多少s后即使还有数据他也不要了,也不行。
...
相信通过配置curl_easy_setopt()函数应该是最官方的做法,但小弟不才没有找到相关文章,自己研究也没搞出来,有待高人指点。
方法3(可行,有缺陷)
万般无奈之下,突然想到既然curl[idx]收到的数据在rcvbuf[idx]中,为何不直接检查rcvbuf[idx]中有没有数据,如下代码3:
//执行多个url,并解析数据
while(running_handles)
{
if (- == curl_multi_select(curl_m))
{
printf("curl_multi_select error !\n");
break;
}
else {
// select监听到事件,调用curl_multi_perform通知curl执行相应的操作 //
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles));
//检测哪一个curl[idx]来的数据
int idx = ;
for (idx = ; idx < CURL_NUM; ++idx)
{
if (rcvbuf[idx][] == NULL) //curl[idx]没有收到数据。
continue;
printf("curl[%d] rcvbuf:\n%s\n", idx, rcvbuf[idx]);
//数据处理...
memset(rcvbuf[idx], , sizeof(rcvbuf[idx]));
}
}
}
通过上面的处理确实能满足要求,但是方法有些笨,存在2个明显的缺陷:
1. 每次都要检测所有的curl一遍,效率低;
2. 一旦某个curl因某种原因死掉了,我该如何判断是哪一个curl挂了?
所以处理这个问题是否有官方的方法?还有待高人解答,保持关注更新。
最新文章
- SignalR —— Asp.net RealTime的春天
- Mysql Cluster配置基本篇
- hdu 2578 Dating with girls(1)
- android开发中遇到的问题
- IntelliJ IDEA 使用教程 - AS3篇
- freemarker.core.InvalidReferenceException: Expression stackObject.value.get(propertyName).toString() is undefined
- Android(java)学习笔记178:BroadcastReceiver之 自定义广播
- nginx的请求接收流程(二)
- Spring(二)
- 201521123055 《Java程序设计》第8周学习总结
- golang的GET请求(类似于PHP的CURL)
- logback中批量插入数据库的参考代码
- CUDA学习,查看device性能参数
- 使用Jenkins时,如果GIT_COMMIT无变化,跳过构建
- C# Aspose.Cells 如何设置单元格样式
- linux配置supervisor
- ng 的 ng-repeat(对象) 把对象的 key 和value 都拿出来 循环
- 学习yii2.0——基础入门
- Python之路PythonNet,第二篇,网络2
- python添加fluent日志记录