libcurl异步非阻塞通信的简单使用

最近用到了libcurl异步非阻塞方式进行通信,在此简单记录一下。主要是用curl_multi_perform,libcurl相关文档链接https://curl.se/libcurl/c/curl_multi_perform.html

代码如下:  

 

  1 #include <curl.h>
  2 #include <chrono>
  3 #include <thread>
  4 #include <iostream>
  5 #include <string>
  6 #ifdef _WIN32
  7 #include <WinSock2.h>
  8 #include <Windows.h>
  9 #endif
 10 
 11 struct uri
 12 {
 13     CURL* easy_handle = NULL;
 14 };
 15 
 16 CURLM* _multi_handle = NULL;
 17 bool _is_running = false;
 18 
 19 void check_multi_info()
 20 {
 21     struct CURLMsg* m = NULL;
 22     do
 23     {
 24         int msgq = 0;
 25         m = curl_multi_info_read(_multi_handle, &msgq);
 26         if (m && (m->msg == CURLMSG_DONE))
 27         {
 28             // 当前easy handle 已接收完所有消息,清除easy handle
 29             CURL* e = m->easy_handle;
 30             curl_multi_remove_handle(_multi_handle, e);
 31             curl_easy_cleanup(e);
 32 
 33             _is_running = false;
 34         }
 35     } while (m);
 36     return;
 37 }
 38 
 39 void process()
 40 {
 41     while (_is_running)
 42     {
 43         int running_handle_count;
 44         while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(_multi_handle, &running_handle_count))
 45         {
 46         }
 47 
 48         while (running_handle_count)
 49         {
 50             timeval tv;
 51             tv.tv_sec = 1;
 52             tv.tv_usec = 0;
 53 
 54             int max_fd;
 55             fd_set fd_read;
 56             fd_set fd_write;
 57             fd_set fd_except;
 58 
 59             FD_ZERO(&fd_read);
 60             FD_ZERO(&fd_write);
 61             FD_ZERO(&fd_except);
 62 
 63             curl_multi_fdset(_multi_handle, &fd_read, &fd_write, &fd_except, &max_fd);
 64             int return_code = select(max_fd + 1, &fd_read, &fd_write, &fd_except, &tv);
 65             if (-1 == return_code)
 66             {
 67                 break;
 68             }
 69             else
 70             {
 71                 while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(_multi_handle, &running_handle_count))
 72                 {
 73                 }
 74             }
 75         }
 76 
 77         check_multi_info();
 78 
 79         std::this_thread::sleep_for(std::chrono::nanoseconds(1));
 80     }
 81     curl_multi_cleanup(_multi_handle);
 82     return;
 83 }
 84 
 85 size_t write_callback(char* buffer, size_t size, size_t nmemb, void* uri)
 86 {
 87     std::cout << buffer << std::endl;
 88     return size * nmemb;
 89 }
 90 
 91 size_t header_callback(const char* ptr, size_t size, size_t nmemb, void* uri)
 92 {
 93     std::cout << "[header_callback] " << ptr << std::endl;
 94     return size * nmemb;
 95 }
 96 
 97 void test(const char* url)
 98 {
 99     curl_global_init(CURL_GLOBAL_ALL);
100 
101     _is_running = true;
102     std::thread th(process);
103 
104     uri _uri;
105     CURL* easy_handle = curl_easy_init();
106     _uri.easy_handle = easy_handle;
107     curl_easy_setopt(easy_handle, CURLOPT_URL, url);
108 
109     // 设置获取返回内容的回调函数
110     curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_callback);
111     curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &_uri);
112 
113     // 设置获取头信息的回调函数   
114     curl_easy_setopt(easy_handle, CURLOPT_HEADERFUNCTION, header_callback);
115     curl_easy_setopt(easy_handle, CURLOPT_HEADERDATA, &_uri);
116 
117     curl_multi_add_handle(_multi_handle, easy_handle);
118 
119     th.join();
120 
121     curl_global_cleanup();
122 
123     return;
124 }
125 
126 int main(int argc, char* argv[])
127 {
128     if (argc < 2)
129     {
130         std::cout << "usage:" << argv[0] << " <url>" << std::endl;
131         return 0;
132     }
133 
134     test(argv[1]);
135 
136     return 0;
137 }

 

posted @ 2022-07-08 15:14  风过太平洋  阅读(1400)  评论(0)    收藏  举报