博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c语言libcurl库的异步用法
阅读量:5101 次
发布时间:2019-06-13

本文共 5610 字,大约阅读时间需要 18 分钟。

        multi接口的使用会比easy 接口稍微复杂点,毕竟multi接口是依赖easy接口的,首先粗略的讲下其使用流程:curl_multi _init初始化一个multi curl对象,为了同时进行多个curl的并发访问,我们需要初始化多个easy curl对象,使用curl_easy_setopt进行相关设置,然后调用curl_multi _add_handle把easy curl对象添加到multi curl对象中,添加完毕后执行curl_multi_perform方法进行并发的访问,访问结束后curl_multi_remove_handle移除相关easy curl对象,curl_easy_cleanup清除easy curl对象,最后curl_multi_cleanup清除multi curl对象。

#include 
#include
#include
#include
#include
using namespace std;size_t curl_writer(void *buffer, size_t size, size_t count, void * stream){ std::string * pStream = static_cast
(stream); (*pStream).append((char *)buffer, size * count); return size * count;};/** * 生成一个easy curl对象,进行一些简单的设置操作 */CURL * curl_easy_handler(const std::string & sUrl, const std::string & sProxy, std::string & sRsp, unsigned int uiTimeout){ CURL * curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, sUrl.c_str()); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); if (uiTimeout > 0) { curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, uiTimeout); } if (!sProxy.empty()) { curl_easy_setopt(curl, CURLOPT_PROXY, sProxy.c_str()); } // write function // curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_writer); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sRsp); return curl;}/** * 使用select函数监听multi curl文件描述符的状态 * 监听成功返回0,监听失败返回-1 */int curl_multi_select(CURLM * curl_m){ int ret = 0; struct timeval timeout_tv; fd_set fd_read; fd_set fd_write; fd_set fd_except; int max_fd = -1; // 注意这里一定要清空fdset,curl_multi_fdset不会执行fdset的清空操作 // FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_except); // 设置select超时时间 // timeout_tv.tv_sec = 1; timeout_tv.tv_usec = 0; // 获取multi curl需要监听的文件描述符集合 fd_set // curl_multi_fdset(curl_m, &fd_read, &fd_write, &fd_except, &max_fd); /** * When max_fd returns with -1, * you need to wait a while and then proceed and call curl_multi_perform anyway. * How long to wait? I would suggest 100 milliseconds at least, * but you may want to test it out in your own particular conditions to find a suitable value. */ if (-1 == max_fd) { return -1; } /** * 执行监听,当文件描述符状态发生改变的时候返回 * 返回0,程序调用curl_multi_perform通知curl执行相应操作 * 返回-1,表示select错误 * 注意:即使select超时也需要返回0,具体可以去官网看文档说明 */ int ret_code = ::select(max_fd + 1, &fd_read, &fd_write, &fd_except, &timeout_tv); switch(ret_code) { case -1: /* select error */ ret = -1; break; case 0: /* select timeout */ default: /* one or more of curl's file descriptors say there's data to read or write*/ ret = 0; break; } return ret;}#define MULTI_CURL_NUM 3// 这里设置你需要访问的url //std::string URL = "http://website.com";// 这里设置代理ip和端口 //std::string PROXY = "ip:port";// 这里设置超时时间 //unsigned int TIMEOUT = 2000; /* ms *//** * multi curl使用demo */int curl_multi_demo(int num){ // 初始化一个multi curl 对象 // CURLM * curl_m = curl_multi_init(); std::string RspArray[num]; CURL * CurlArray[num]; // 设置easy curl对象并添加到multi curl对象中 // for (int idx = 0; idx < num; ++idx) { CurlArray[idx] = NULL; CurlArray[idx] = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT); if (CurlArray[idx] == NULL) { return -1; } curl_multi_add_handle(curl_m, CurlArray[idx]); } /* * 调用curl_multi_perform函数执行curl请求 * url_multi_perform返回CURLM_CALL_MULTI_PERFORM时,表示需要继续调用该函数直到返回值不是CURLM_CALL_MULTI_PERFORM为止 * running_handles变量返回正在处理的easy curl数量,running_handles为0表示当前没有正在执行的curl请求 */ int running_handles; while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles)) { cout << running_handles << endl; } /** * 为了避免循环调用curl_multi_perform产生的cpu持续占用的问题,采用select来监听文件描述符 */ while (running_handles) { if (-1 == curl_multi_select(curl_m)) { cerr << "select error" << endl; break; } else { // select监听到事件,调用curl_multi_perform通知curl执行相应的操作 // while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &running_handles)) { cout << "select: " << running_handles << endl; } } cout << "select: " << running_handles << endl; } // 输出执行结果 // int msgs_left; CURLMsg * msg; while((msg = curl_multi_info_read(curl_m, &msgs_left))) { if (CURLMSG_DONE == msg->msg) { int idx; for (idx = 0; idx < num; ++idx) { if (msg->easy_handle == CurlArray[idx]) break; } if (idx == num) { cerr << "curl not found" << endl; } else { cout << "curl [" << idx << "] completed with status: " << msg->data.result << endl; cout << "rsp: " << RspArray[idx] << endl; } } } // 这里要注意cleanup的顺序 // for (int idx = 0; idx < num; ++idx) { curl_multi_remove_handle(curl_m, CurlArray[idx]); } for (int idx = 0; idx < num; ++idx) { curl_easy_cleanup(CurlArray[idx]); } curl_multi_cleanup(curl_m); return 0;}/** * easy curl使用demo */int curl_easy_demo(int num){ std::string RspArray[num]; for (int idx = 0; idx < num; ++idx) { CURL * curl = curl_easy_handler(URL, PROXY, RspArray[idx], TIMEOUT); CURLcode code = curl_easy_perform(curl); cout << "curl [" << idx << "] completed with status: " << code << endl; cout << "rsp: " << RspArray[idx] << endl; // clear handle // curl_easy_cleanup(curl); } return 0;}#define USE_MULTI_CURLstruct timeval begin_tv, end_tv;int main(int argc, char * argv[]){ if (argc < 2) { return -1; } int num = atoi(argv[1]); // 获取开始时间 // gettimeofday(&begin_tv, NULL);#ifdef USE_MULTI_CURL // 使用multi接口进行访问 // curl_multi_demo(num);#else // 使用easy接口进行访问 // curl_easy_demo(num);#endif // 获取结束时间 // struct timeval end_tv; gettimeofday(&end_tv, NULL); // 计算执行延时并输出,用于比较 // int eclapsed = (end_tv.tv_sec - begin_tv.tv_sec) * 1000 + (end_tv.tv_usec - begin_tv.tv_usec) / 1000; cout << "eclapsed time:" << eclapsed << "ms" << endl; return 0;}

 

转载自: http://blog.csdn.net/zxgfa/article/details/8220724

转载于:https://www.cnblogs.com/zhaoyl/p/4001151.html

你可能感兴趣的文章
MySQL更改默认的数据文档存储目录
查看>>
替代微软IIS强大的HTTP网站服务器工具
查看>>
6.5 案例21:将本地数据库中数据提交到服务器端
查看>>
PyQt5--EventSender
查看>>
android 通过AlarmManager实现守护进程
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>
win7下把电脑设置成wlan热
查看>>
Java 多态 虚方法
查看>>
jquery.validate插件在booststarp中的运用
查看>>
java常用的包
查看>>
PHP批量覆盖文件并执行cmd命令脚本
查看>>
Unity之fragment shader中如何获得视口空间中的坐标
查看>>
支持向量机——内核
查看>>
万能的SQLHelper帮助类
查看>>
uboot分析:uboot的启动过程分析
查看>>
tmux的简单快捷键
查看>>
springboot笔记04——读取配置文件+使用slf4j日志
查看>>
[Swift]LeetCode653. 两数之和 IV - 输入 BST | Two Sum IV - Input is a BST
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
微信小程序的wxml文件和wxss文件在webstrom的支持
查看>>