前提概要

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

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

libcurl 中使用curl_multi_perform()函数执行订阅类型url的问题的更多相关文章

  1. 【C#】C#中方法(函数)的类型有哪些

    目录结构: contents structure [+] 构造函数 引用类型的构造函数 值类型的构造函数 析构函数 析构函数的使用 析构函数和Dispose()方法的区别 操作符重载 转化操作符方法 ...

  2. Jquery Mobile中pageinit等函数执行两次的问题【终极解决】

    当禁用了jqueryMobile的ajax后,初始化函数如pageinit和pageshow等函数,都会执行两次.document.ready函数也会执行两次. 当然我们可以用一个变量记录是否已经执行 ...

  3. plv8 中使用 eval 函数执行表达式计算

    在js 开发中我们都说eval 函数是邪恶的,但是此函数也有好多妙用,以下是几个简单的案例 eval 执行基于js 的表达式计算 比如我们有以下表 CREATE TABLE rules (    id ...

  4. 在Loadrunner中如何用system函数执行系统命令

    前提: windows 系统 实现功能:用 LR 中的system函数执行系统命令 相关功能:在LR中利用C函数建立文件,写文件,读文件. 主要相关函数:sprintf/fopen/fgetc/fre ...

  5. C++构造与析构函数中调用虚函数的问题

    前些天想把以前写的内存池算法重写一遍,跨平台是第一目标,当时突发奇想,因为不愿意做成一大堆#if..#end,所以想利用C++的多态性,但是怎么让内存池完好退出却没想到自认为完美的方案.但是一个很偶然 ...

  6. PHP中的CURL函数库

    PHP中的CURL函数库(Client URL Library Function) curl_close — 关闭一个curl会话curl_copy_handle — 拷贝一个curl连接资源的所有内 ...

  7. 关于js中的回调函数callback

    来源于:http://www.jianshu.com/p/6bc353e5f7a3 前言 其实我一直很困惑关于js 中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制 ...

  8. 关于 js 中的回调函数 callback

    本文写于1年前 曾经的学习文章如今拿出来分享 前言 其实我一直很困惑关于js中的callback,困惑的原因是,学习中这块看的资料少,但是平时又经常见,偶尔复制一下前人代码,功能实现了也就不再去追其原 ...

  9. golang函数——可以为类型(包括内置数据类型)定义函数,类似类方法,同时支持多返回值

    不可或缺的函数,在Go中定义函数的方式如下: func (p myType ) funcName ( a, b int , c string ) ( r , s int ) { return } 通过 ...

随机推荐

  1. 队列 和 堆栈用python 来实现

    一.利用python列表实现堆栈和队列 堆栈: 堆栈是一个后进先出的数据结构,其工作方式就像生活中常见到的直梯,先进去的人肯定是最后出. 我们可以设置一个类,用列表来存放栈中的元素的信息,利用列表的a ...

  2. sharepoint_study_2

    描述:向SharePoint中批量添加用户 解决:原文地址:http://bbs.winos.cn/thread-89236-1-1.html 一般情况下,要想登录SharePoint server ...

  3. Python- sort()/sorted()

    Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. sorted(iterable,key=None,revers ...

  4. numpy-1

    NumPy数组 NumPy数组是一个多维数组对象,称为ndarray.其由两部分组成: 实际的数据 描述这些数据的元数据 大部分操作仅针对于元数据,而不改变底层实际的数据. 关于NumPy数组有几点必 ...

  5. IOS不支持overflow: hidden;

    IOS不支持overflow: hidden; 假设页面上有个弹出窗,弹出窗出现后,只想让用户的视觉锁定在弹出窗上,正常我们会想到用overflow:hidden这个属性来实现,如下 html{ ov ...

  6. [转] 用javascript修改css伪类的几种方法

    用javascript修改css伪类的几种方法: Modify pseudo element styles with JavaScript http://pankajparashar.com/post ...

  7. Valgrind 检测程序内存使用

    Valgrind是用于构建动态分析工具的探测框架.它包括一个工具集,每个工具执行某种类型的调试.分析或类似的任务,以帮助完善你的程序.Valgrind的架构是模块化的,所以可以容易地创建新的工具而又不 ...

  8. python数据类型,格式话输出

    一.程序交互 name = input(“你的名字是:”) #用户输入,输入的任何东西都存储成str(字符串类型)的形式 二.注释的重要性 以后动辄几千行代码的时候,回过头再去看的时候,发现自己都看不 ...

  9. 小众软件:Windows 下优化软件推荐—— Dism++ | 强迫症晚期患者福音 - 少数派

    Windows 下优化软件推荐—— Dism++ | 强迫症晚期患者福音 - 少数派 https://sspai.com/post/41992 官方网站免费下载

  10. http请求报头和响应报头(1)

    1.web端不可避免的http缓存机制,要理解缓存机制,先来了解下http的请求报文和响应报文的内容 2.请求报文  2.1请求行    请求行三部分组成:请求方法.URL以及版本协议 请求的方法有G ...