Using libcurl for HTTP communication in C + +

TssiNG-Z 2021-02-23 01:04:31
using libcurl http communication


Borrow curl 7.75.0 Version update , Recently, I downloaded it to play , Here's a brief note

1. Environment building

First of all libcurl Dynamic library , If you want to download the source code and compile it yourself https The agreement has to be downloaded OpenSSL and libssh Source code compiled together , I'm in trouble , So the official compiled dynamic library downloaded directly from the official website

linux Generally, it comes with or directly apt get It's very convenient

Put one here windows The download address of the environment : https://curl.se/windows/

 

The red box is curl The dependency Library of some functions , Here I suggest that you download them and throw them into the project directory

 

Download it and unzip it curl The directory structure is shown in the figure above , among bin It's a dynamic library , lib Is a static library , include It's the header file , It needs to be mentioned that lib Both static libraries in are .a At the end of the , Small and with dll Should be windows Version of , I changed the static library name to libcurl.lib

 

  Finally, I'll look at the dynamic libraries that I might use , Static library , certificate , Header file integration , The contents are as follows :

Then link in your own program libcurl, contain curl The header file in the directory , take dll Put it in the same directory as the executable program and you can start to use it .

 

2. Call the interface to http Communications

Let's start with curl Basic process and important variables of request

(1) CURLcode curl_global_init() : This interface is used to initialize curl library , It should be in all curl Operation is called before

(2) CURL* curl_easy_init() : The interface returns a curl Handle , The type is CURL*, All operations related to a session are performed on this return handle

(3) void curl_easy_cleanup(CURL*) : This interface is used to release the given curl Handle , This interface should be called at the end of each session to release the corresponding curl Handle

(4) CURLcode curl_easy_setopt(CURL*, CURLoption, ...) : The interface can be set and specified by passing in different macros curl Handle properties , In order to control the various properties of the session

Here is an official link to check OPT The meaning of , It also includes official example : https://curl.se/libcurl/c/curl_easy_setopt.html

(5) CURLcode curl_easy_perform(CURL*) : Execute a communication session through a given handle

(6) CURLcode : Almost all curl The return value of the interface is of this type , This code All defined curl State of operation , Here is an official link to check code The meaning of : https://curl.se/libcurl/c/libcurl-errors.html

(7) const char* curl_easy_strerror(CURLcode) : take CURLcode To the corresponding meaning of the string, convenient for log output and other operations

That's what I use all the time curl Interface , curl Powerful , The protocols and content supported go far beyond http/https

The official evaluation is : libcurl is probably the most portable, most powerful and most often used network transfer library on this planet.

Here I encapsulate two functions , Namely http GET Request web pages and http GET Download the file , In the process cookie.

Code up :

Self encapsulated curl class

 1 class CHttpClient
 2 {
 3 public:
 4  CHttpClient();
 5 ~CHttpClient();
 6
 7 long http_enable_cookie(const char *path);
 8 long http_post(const char *url);
 9 long http_submit(const char *url, std::vector<std::string> &form);
10 long http_get(const char *url, std::string &body);
11 long http_download(const char *url, const char *fullpath);
12 long http_add_header(const char *header);
13 long http_add_multi_header(std::vector<std::string> &list);
14
15 private:
16 bool prepare_curl(const char *url);
17 bool exec_curl();
18 bool try_cleanup_curl();
19
20 private:
21 CURL *m_pCurl;
22 struct curl_slist *m_pHeader;
23 bool m_bSetCookie;
24 bool m_bSetHeader;
25 char m_szCookiePath[MAX_PATH];
26 };

Most important curl_global_init In the constructor , No more here , among prepare_curl, exec_curl, try_cleanup_curl For me curl http Basic encapsulation of communication flow

Here are three interfaces

 1 bool CHttpClient::prepare_curl(const char *url)
 2 {
 3 m_pCurl = curl_easy_init();
 4 if (nullptr == m_pCurl) return false;
 5
 6  curl_easy_setopt(m_pCurl, CURLOPT_URL, url);
 7 curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);
 8 curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
 9 curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
10
11 if (m_bSetHeader)
12  {
13  curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, m_pHeader);
14  }
15
16 if (m_bSetCookie)
17  {
18 curl_easy_setopt(m_pCurl, CURLOPT_COOKIEJAR, m_szCookiePath); //set-cookie This path will be modified to correspond to cookie Cache file 
19 curl_easy_setopt(m_pCurl, CURLOPT_COOKIEFILE, m_szCookiePath); // When the request is sent, it will be read from this file cookie
20  }
21
22 #ifdef DEBUG
23 curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE, 1L);
24  curl_easy_setopt(m_pCurl, CURLOPT_DEBUGFUNCTION, cb_dbg);
25 #endif
26
27 return true;
28 }
29
30 bool CHttpClient::exec_curl()
31 {
32 CURLcode retCode = curl_easy_perform(m_pCurl);
33  try_cleanup_curl();
34
35 #ifdef DEBUG
36  print_dbg_msg();
37 #endif
38
39 if (CURLE_OK != retCode)
40  {
41 LOG_MSG(LOG_ERROR, "curl execute with code[%d] msg[%s]", retCode, curl_easy_strerror(retCode));
42 return false;
43  }
44 return true;
45 }
46
47 bool CHttpClient::try_cleanup_curl()
48 {
49 if (nullptr != m_pCurl)
50  {
51  curl_easy_cleanup(m_pCurl);
52 m_pCurl = nullptr;
53  }
54
55 if (m_bSetHeader)
56  {
57  curl_slist_free_all(m_pHeader);
58 m_pHeader = nullptr;
59 m_bSetHeader = false;
60  }
61
62 return true;
63 }

prepare_curl Mainly on curl Handle initialization , Set up http General parameters

exec_curl perform curl Communications , After the communication is completed, it is called try_cleanup_curl Memory free , And print debug Communications

in the light of prepare_curl in curl_easy_setopt Parameters of , Here's an explanation

(1)CURLOPT_URL : http Address of correspondence , Can resolve domain names

(2)CURLOPT_FOLLOWLOCATION : Follow page redirection

(3)CURLOPT_SSL_VERIFYPEER & CURLOPT_SSL_VERIFYHOST : Whether or not the two ends are SSL Security verification , Here I turn this off , Normal production environment will not do this , curl There are also certificates in the library , The old version may need to update the certificate to prevent some web pages from being inaccessible , I only do debugging here , It's more casual

(4)CURLOPT_HTTPHEADER : Set up http header, Incoming here curl_slist Structure , Use curl_slist_append You can directly const char* The type string is added to this structure , If not set , curl The default request header is GET, Accept,Host

(5)CURLOPT_COOKIEJAR : Specify this communication cookie Saved path , The save operation is in the corresponding curl Handle execution curl_easy_cleanup When the

(6)CURLOPT_COOKIEFILe : Specify this communication cookie Read path

(7)CURLOPT_VERBOSE : Set whether to echo the communication content , If the callback function is not specified after opening , Then use stderr

(8)CURLOPT_DEBUGFUNCTION : Set the callback function to call when echoing , The parameter list of the callback function should be (CURL *curl, curl_infotype type, char *data, size_t size, void *usr_ptr), among type Indicates the current data The type of , Types include CURLINFO_TEXT, CURLINFO_HEADER_IN, CURLINFO_HEADER_OUT, CURLINFO_DATA_IN, CURLINFO_DATA_OUT, CURLINFO_SSL_DATA_IN, CURLINFO_SSL_DATA_OUT, CURLINFO_END, The specific meaning refers to the official document, the actual debugging is easier to understand

Let's show CURLOPT_DEBUGFUNCTION The corresponding callback function and print_dbg_msg Print function

 1 static std::string g_sHeaderOut;
 2 static std::string g_sHeaderIn;
 3 static std::string g_sDataOut;
 4 static std::string g_sDataIn;
 5
 6 int cb_dbg(CURL *curl, curl_infotype type, char *data, size_t size, void *usr_ptr)
 7 {
 8 switch (type)
 9  {
10 case CURLINFO_HEADER_OUT:
11  g_sHeaderOut.append(data, size);
12 break;
13 case CURLINFO_DATA_OUT:
14  g_sDataOut.append(data, size);
15 break;
16 case CURLINFO_HEADER_IN:
17  g_sHeaderIn.append(data, size);
18 break;
19 case CURLINFO_DATA_IN:
20  g_sDataIn.append(data, size);
21 break;
22 default:
23 break;
24  }
25 return 0;
26 }
27
28 void print_dbg_msg()
29 {
30 if (!g_sHeaderOut.empty())
31  {
32 str_replace(g_sHeaderOut, "%", "%%");
33 LOG_MSG(LOG_DEBUG, "%s", g_sHeaderOut.c_str());
34  g_sHeaderOut.clear();
35  }
36
37 if (!g_sDataOut.empty())
38  {
39 str_replace(g_sDataOut, "%", "%%");
40 LOG_MSG(LOG_DEBUG, "%s", g_sDataOut.c_str());
41  g_sDataOut.clear();
42  }
43
44 if (!g_sHeaderIn.empty())
45  {
46 str_replace(g_sHeaderIn, "%", "%%");
47 LOG_MSG(LOG_DEBUG, "%s", g_sHeaderIn.c_str());
48  g_sHeaderIn.clear();
49  }
50
51 if (!g_sDataIn.empty())
52  {
53 str_replace(g_sDataIn, "%", "%%");
54 LOG_MSG(LOG_DEBUG, "%s", g_sDataIn.c_str());
55  g_sDataIn.clear();
56  }
57 }

Here because I write my own log to print and use vsprinf encounter % Will report a mistake , Here I've encapsulated another string Of replace Function % Replace with %%, It may not look good when printing , I haven't taken the time to optimize

Let's show GET Request and GET download request

 1 long CHttpClient::http_get(const char *url, std::string &res)
 2 {
 3 if (!prepare_curl(url)) return TSI_INTERNAL_ERR;
 4
 5 // CURLOPT_WRITEDATA The following parameters will be passed to the callback function usrdata
 6  curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, cb_get);
 7 curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, &res);
 8
 9 if (!exec_curl())
10  {
11 LOG_MSG(LOG_ERROR, "http get fail");
12 return TSI_INTERNAL_ERR;
13  }
14 return TSI_NO_ERR;
15 }
16
17 long CHttpClient::http_download(const char *url, const char *fullpath)
18 {
19 if (!prepare_curl(url)) return TSI_INTERNAL_ERR;
20
21 // Binary write mode creates Download File 
22 FILE *download_file = fopen(fullpath, "wb");
23 if (nullptr == download_file)
24  {
25  try_cleanup_curl();
26 return TSI_INTERNAL_ERR;
27  }
28
29 // Set the file handle to the download callback , curl Internally, the large file will be divided and callbacks will be called many times to write data 
30  curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, cb_download);
31  curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, download_file);
32
33 //TODO: To determine if the download process is asynchronous , Prevent files from being downloaded , Just behind fclose 了 
34 if (!exec_curl())
35  {
36 LOG_MSG(LOG_ERROR, "http download [%s] fail", fullpath);
37  fclose(download_file);
38  std::remove(fullpath);
39 return TSI_INTERNAL_ERR;
40  }
41
42 LOG_MSG(LOG_INFO, "http download [%s] success", fullpath);
43  fclose(download_file);
44 return TSI_NO_ERR;
45 }

Two of them are involved CURLOPT, Here is an explanation

(1)CURLOPT_WRITEFUNCTION : This parameter specifies get Write method of the requested content , curl By default fwrite, The callback function parameter list must be (char *data, size_t size, size_t nmemb, void *usrdata)

(2)CURLOPT_WRITEDATA : This parameter passes the following data as a parameter to the specified writefunction in

Here are two callback functions cb_get and cb_download

 1 size_t cb_get(char *data, size_t size, size_t nmemb, void *usrdata)
 2 {
 3 size_t data_size = size * nmemb;
 4 static_cast<std::string*>(usrdata)->append(data, data_size);
 5 return data_size;
 6 }
 7
 8 size_t cb_download(char *data, size_t size, size_t nmemb, void *usrdata)
 9 {
10 size_t data_size = size * nmemb;
11 fwrite(data, size, nmemb, (FILE*)usrdata);
12 return data_size;
13 }

because download The function involves the analysis of specific websites , No debugging is shown here

Above is http get A simple example of a request , Common functions should also have form POST, Not for the time being , I'll make it up when I have time .

If there is any mistake or omission , Be sure to point out , Thank you very much. , At the same time, welcome to discuss related issues together , Reprint please indicate , thank !

版权声明
本文为[TssiNG-Z]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/02/20210222180503739c.html

  1. vue判断elementui中el-form是否更新变化,变化就提示是否保存,没变就直接离开
  2. 算法题:两数之和——JavaScript及Java实现
  3. 高性能 Nginx HTTPS 调优
  4. Why Vue uses asynchronous rendering
  5. day 31 jQuery进阶
  6. day 30 jQuery
  7. CSS whimsy -- using background to create all kinds of wonderful backgrounds
  8. Why are more and more people learning front end?
  9. What do you do with 4K front-end development?
  10. 8 years of front-end development knowledge precipitation (do not know how many words, keep writing it...)
  11. What is the annual salary of a good web front end?
  12. Front end novice tutorial! How to get started with web front end
  13. Will the front end have a future?
  14. Is the front end hard to learn?
  15. Seven new Vue combat skills to improve efficiency in 2021!
  16. Is front end learning difficult?
  17. How about the process of Web front-end development and self-study?
  18. Front end learning route from zero basis to proficient
  19. What is the basis of learning front end?
  20. What knowledge points need to be learned for self-study front end? How long can I become a front-end Engineer?
  21. An inexperienced front-end engineer, what are the common problems when writing CSS?
  22. HttpServletRequest get URL (parameter, path, port number, protocol, etc.) details
  23. Springboot starts http2
  24. Enabling http2.0 in spring boot
  25. JQuery:JQuery基本语法,JQuery选择器,JQuery DOM,综合案例 复选框,综合案例 随机图片
  26. Using JavaScript in Safari browser history.back () the page will not refresh after returning to the previous page
  27. vue.js Error in win10 NPM install
  28. In less than two months, musk made more than $1 billion, more than Tesla's annual profit
  29. Springboot starts http2
  30. Vue event bus
  31. JQuery easy UI tutorial: custom data grid Pagination
  32. Using okhttp and okhttpgo to obtain onenet cloud platform data
  33. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control
  34. HTTP 1. X learning notes: an authoritative guide to Web Performance
  35. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control
  36. HTTP 1. X learning notes: an authoritative guide to Web Performance
  37. JQuery:JQuery基本语法,JQuery选择器,JQuery DOM,综合案例 复选框,综合案例 随机图片
  38. Event bubble and capture in JavaScript
  39. The root element is missing solution
  40. Event bubble and capture in JavaScript
  41. Configure the certificate to enable ngnix to publish the trusted website of HTTPS
  42. Javascript数据类型
  43. HTTP interface debugging tool! 48000 star HTTP command line client!
  44. Parameter encryption of front end URL link band
  45. HTTP interface debugging tool! 48000 star HTTP command line client!
  46. Three front end frameworks: data binding and data flow
  47. Reading Axios source code (1) -- exploring the realization of basic ability
  48. Event bubble and capture in JavaScript
  49. 【微前端】微前端最終章-qiankun指南以及微前端整體探索
  50. R & D solution e-Car front end monitoring system
  51. [JS] 877 - 35 wonderful knowledge of JavaScript, long experience!
  52. R & D solution e-Car front end monitoring system
  53. High performance nginx HTTPS tuning - how to speed up HTTPS by 30%
  54. 解决ajax跨域问题【5种解决方案】
  55. Top ten classic sorting of JavaScript
  56. HTTP 1. X learning notes: an authoritative guide to Web Performance
  57. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control component
  58. My http / 1.1 is so slow!
  59. Why Vue uses asynchronous rendering
  60. The response status was 0. Check out the W3C XMLHttpRequest Level 2 spec for