前提概要

当需要同时处理多个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挂了?

所以处理这个问题是否有官方的方法?还有待高人解答,保持关注更新。

最新文章

  1. SignalR —— Asp.net RealTime的春天
  2. Mysql Cluster配置基本篇
  3. hdu 2578 Dating with girls(1)
  4. android开发中遇到的问题
  5. IntelliJ IDEA 使用教程 - AS3篇
  6. freemarker.core.InvalidReferenceException: Expression stackObject.value.get(propertyName).toString() is undefined
  7. Android(java)学习笔记178:BroadcastReceiver之 自定义广播
  8. nginx的请求接收流程(二)
  9. Spring(二)
  10. 201521123055 《Java程序设计》第8周学习总结
  11. golang的GET请求(类似于PHP的CURL)
  12. logback中批量插入数据库的参考代码
  13. CUDA学习,查看device性能参数
  14. 使用Jenkins时,如果GIT_COMMIT无变化,跳过构建
  15. C# Aspose.Cells 如何设置单元格样式
  16. linux配置supervisor
  17. ng 的 ng-repeat(对象) 把对象的 key 和value 都拿出来 循环
  18. 学习yii2.0——基础入门
  19. Python之路PythonNet,第二篇,网络2
  20. python添加fluent日志记录

热门文章

  1. 二 ASP.NET MVC 第一个程序 hello world
  2. excel文件的groovy脚本在SoapUI中进行数据驱动测试
  3. javascript JSON. 转换 注意事项
  4. CentOS7 编译安装 php7
  5. 再谈java枚举 ENUM
  6. HTML5实现多文件的上传示例代码
  7. PIE SDK专题制图下屏幕坐标转地图坐标
  8. 设计模式学习总结(十)责任链模式(Chain Of Responsibility)
  9. 转帖 JS的基础语法2
  10. 用poi替换ppt中的文字和图片