libcurl异步访问示例
用同步阻塞的方式跑单线程效率太低,每次开新线程去跑curl太浪费资源,没有必要。
有没有办法用IO复用的方式跑单线程?libcurl自带的curl_multi_wait(封装了IO复用)可以完成这个工作。
参考地址:
https://www.cnblogs.com/heluan/p/10177475.html
https://blog.csdn.net/whui19890911/article/details/79320408
https://www.cnblogs.com/bugutian/p/4868167.html
https://www.cnblogs.com/dvss/archive/2013/04/11/3014699.html
代码示例:
#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <list>
#include <map>
#include <curl/multi.h>
#include <curl/curl.h>
#include <curl/easy.h>
using namespace std;
typedef unsigned long long UInt64;
std::mutex msgListMtx;
std::list<int> msgList;
// 这里设置你需要访问的url //
std::string BASE_URL = "http://192.168.1.135:19090/vinput?key=";
// 这里设置代理ip和端口 //
std::string PROXY = "";
// 这里设置超时时间 //
unsigned int TIMEOUT = 2000; /* ms */
unsigned int globalCnt = 0;
typedef struct SReqNode{
std::string url;
std::string respData;
unsigned int seq;
SReqNode()
{
seq = 0;
url = "";
respData = "";
}
} SReqNode;
size_t curl_writer(void *buffer, size_t size, size_t count, void * stream)
{
std::string * pStream = static_cast<std::string *>(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_WRITEFUNCTION, curl_writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sRsp);
return curl;
}
void dealMsg(SReqNode* reqNodePtr,int status)
{
cout << "curl [" << reqNodePtr->seq << "] status: "
<< status << ",says: "
<< reqNodePtr->respData << endl;
}
void dealErr()
{
cout << "Response Msg is not found." << endl;
}
int key_send_thread()
{
// 初始化一个multi curl 对象 //
CURLM * curl_m = curl_multi_init();
std::map<UInt64,SReqNode*> handle2rsp;
while (1)
{
std::list<int> tmpKeys;
msgListMtx.lock();
tmpKeys.swap(msgList);
msgListMtx.unlock();
//cout << "SIZE:" << tmpKeys.size() << endl;
std::list<int>::iterator iter = tmpKeys.begin();
for (;iter != tmpKeys.end();iter ++)
{
CURL* tmpHandler = NULL;
std::string tmpUrl = BASE_URL + std::to_string(*iter) + "&";
SReqNode* tmpReqNode = new SReqNode();
tmpReqNode->seq = globalCnt++;
tmpReqNode->url = tmpUrl;
tmpHandler = curl_easy_handler(tmpUrl, PROXY, tmpReqNode->respData, TIMEOUT);
if (tmpHandler == NULL)
{
continue;
}
handle2rsp[(UInt64)tmpHandler] = tmpReqNode;
curl_multi_add_handle(curl_m, tmpHandler);
}
/*
* 调用curl_multi_perform函数执行curl请求
* url_multi_perform返回CURLM_CALL_MULTI_PERFORM时,表示需要继续调用该函数, 直到返回值不是CURLM_CALL_MULTI_PERFORM为止
* running_handles变量返回正在处理的easy curl数量,running_handles为0表示当前没有正在执行的curl请求
*/
int runningHandles;
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curl_m, &runningHandles))
{
cout << runningHandles << endl;
}
int numfds,msgs_left,res;
res = curl_multi_wait(curl_m, NULL, 0, 200, &numfds);
CURLMsg * msg;
while((msg = curl_multi_info_read(curl_m, &msgs_left)))
{
cout << "while curl_multi_info_read:" << endl;
if (CURLMSG_DONE == msg->msg)
{
int idx;
std::map<UInt64, SReqNode*>::iterator iter2 = handle2rsp.find(UInt64(msg->easy_handle));
if (iter2 != handle2rsp.end())
{
dealMsg(iter2->second, msg->data.result);
SReqNode* tmpPrt = iter2->second;
handle2rsp.erase(iter2);
curl_multi_remove_handle(curl_m, msg->easy_handle);
curl_easy_cleanup( msg->easy_handle);
delete tmpPrt;
}else{
dealErr();
}
}
}
}
curl_multi_cleanup(curl_m);
return 0;
}
int main()
{
thread senderThread(key_send_thread);
int input;
while(1)
{
cout << "input:";
cin >> input;
if (input == 3306)
{
break;
}
msgListMtx.lock();
msgList.push_back(input);
msgListMtx.unlock();
}
senderThread.join();
return 0;
}
/********************
### 编译
g++ testcurl.cpp -I/usr/local/sdk/include -I/usr/local/sdk/include/curl -lidn -lrt -lcrypto -lssl -lz -lpthread /usr/local/sdk/lib/libcurl.a -std=c++11 -o testurl
### 运行
[root@lh]# ./testurl
input:
654
input:while curl_multi_info_read:
curl [0] status: 0,says: Recv:654
6546
input:while curl_multi_info_read:
curl [1] status: 0,says: Recv:6546
46
*********************/
转载请注明来源:https://www.cnblogs.com/bugutian/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」