0


VS2019利用Curl库实现HTTP网络通信(C++)

  1. C++实现HTTP网络通信,一般采用两种方式,熟悉TCP协议的大哥可能不需要查这方面的知识;还有一种方式就是使用第三方库,Qt环境下可以用QNetworkRequest实现很方便,再就是Curl了,Curl是个独立的第三方库,不依赖于qt环境,可以实现GETPOST方式通信。

​ 先说环境,VS2019;

一、Curl环境搭建

​ 调用Curl的静态库/动态库是需要自己编译的;

1.1 文件下载

​ 打开下载地址(curl - Download)下载对应版本的curl压缩包,本文下载7.65.0版本(也尝试了新版的7.8.0,但下一步编译未成功);

1.2 编译

​ 下载好的文件解压缩到指定文件夹,然后双击运行【../curl-7.65.0/buildconf.bat】,一闪而过就结束了;

  1. 在开始菜单的VS中找到【x64 Native Tools Command Prompt for VS 2019】,点击打开;

  1. 进入到【../curl-7.65.0/winbuild】目录下,执行【nmake /f Makefile.vc mode=static VC=15 MACHINE=x64 DEBUG=no】;
  2. 参数含义:
  1. nmake /f Makefile.vc mode=static // 静态编译,也可mode=dll
  2. VC=15 // vc版本
  3. MACHINE=x64 // 64或32位
  4. DEBUG=no // 改成yes就是Debug

  1. 等待两三分钟,编译完成进入【../curl-7.65.0/builds】可见以下文件,第一个就是我们需要的,至此编译完成;

1.3 Curl开发环境配置

  1. 新建一个测试工程,由于名字太长,将1.2步骤编译生成的文件夹重命名为【curl】,内含如下文件夹;

  1. 右键工程属性,在VC++选项卡内,分别设置包含目录【../curl/include】库目录【../curl/lib】;

  1. C/C++选项卡,预处理器添加【CURL_STATICLIB】;

链接器/输入选项卡,附加依赖项添加

  1. libcurl_a.lib
  2. Ws2_32.lib
  3. Wldap32.lib
  4. winmm.lib
  5. Crypt32.lib
  6. Normaliz.lib

  1. 至此环境搭建完成,后续就可以在项目中正常使用了。

二、利用Curl库实现HTTP网络通信

2.1 测试

  1. 测试代码如下:
  1. #include <curl/curl.h>
  2. void testCurlFunc() {
  3. CURL* curl = 0;
  4. CURLcode res;
  5. curl = curl_easy_init();
  6. if (curl != 0) {
  7. // 设置url
  8. curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
  9. //www.baidu.com 可能会跳转,所以设置为跟随跳转
  10. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  11. // 发出请求
  12. res = curl_easy_perform(curl);
  13. // 返回状态检查
  14. if (res != CURLE_OK) {
  15. fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
  16. }
  17. // 任务完成,清理工作
  18. curl_easy_cleanup(curl);
  19. }
  20. }
  1. 打印信息如下所示,表明成功:

2.2 关于打印信息乱码

  1. 可以看到其中中文是乱码,这是由于返回的响应数据是utf编码方式,而debugcout打印是GBK,可以在cout前面加一句【SetConsoleOutputCP(CP_UTF8);】,将打印编码设置为utf8就不乱码了,效果如下;

三、使用CURL发送GET请求

​ 代码如下:

  1. #include<curl\curl.h>
  2. using namespace std;
  3. //get请求和post请求数据响应函数
  4. size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
  5. {
  6. //在注释的里面可以打印请求流,cookie的信息
  7. //cout << "----->reply" << endl;
  8. string *str = (string*)stream;
  9. //cout << *str << endl;
  10. (*str).append((char*)ptr, size*nmemb);
  11. return size * nmemb;
  12. }
  13. //http GET请求
  14. CURLcode curl_get_req(const std::string &url, std::string &response)
  15. {
  16. //curl初始化
  17. CURL *curl = curl_easy_init();
  18. // curl返回值
  19. CURLcode res;
  20. if (curl)
  21. {
  22. //设置curl的请求头,表头类型可能不同
  23. struct curl_slist* header_list = NULL;
  24. header_list = curl_slist_append(header_list, "Content-Type:application/json");
  25. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
  26. //不接收响应头数据0代表不接收 1代表接收
  27. curl_easy_setopt(curl, CURLOPT_HEADER, 0);
  28. //设置请求的URL地址
  29. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  30. //设置ssl验证
  31. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  32. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  33. //CURLOPT_VERBOSE的值为1时,会显示详细的调试信息
  34. curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
  35. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  36. //设置数据接收函数
  37. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
  38. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
  39. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  40. //设置超时时间
  41. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 6); // set transport and time out time
  42. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6);
  43. // 开启请求
  44. res = curl_easy_perform(curl);
  45. }
  46. // 释放curl
  47. curl_easy_cleanup(curl);
  48. return res;
  49. }
  50. int test_curl_get_req()
  51. {
  52. string getUrlStr = "https://www.baidu.com/";
  53. string getResponseStr;
  54. auto res = curl_get_req(getUrlStr, getResponseStr);
  55. if (res == CURLE_OK)
  56. {
  57. cout << getResponseStr << endl;
  58. }
  59. getchar();
  60. return 0;
  61. }
  1. 打印信息如下:

四、使用CURL发送POST请求传递JSON数据

​ 代码如下:

  1. #include<iostream>
  2. #include<string>
  3. #include<curl\curl.h>
  4. using namespace std;
  5. //get请求和post请求数据响应函数
  6. size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
  7. {
  8. //在注释的里面可以打印请求流,cookie的信息
  9. //cout << "----->reply" << endl;
  10. string *str = (string*)stream;
  11. //cout << *str << endl;
  12. (*str).append((char*)ptr, size*nmemb);
  13. return size * nmemb;
  14. }
  15. //http POST请求
  16. CURLcode curl_post_req(const string &url, const string &postParams, string &response)
  17. {
  18. // curl初始化
  19. CURL *curl = curl_easy_init();
  20. // curl返回值
  21. CURLcode res;
  22. if (curl)
  23. {
  24. // set params
  25. //设置curl的请求头
  26. struct curl_slist* header_list = NULL;
  27. header_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
  28. header_list = curl_slist_append(header_list, "Content-Type:application/json; charset=UTF-8");
  29. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
  30. //不接收响应头数据0代表不接收 1代表接收
  31. curl_easy_setopt(curl, CURLOPT_HEADER, 0);
  32. //设置请求为post请求
  33. curl_easy_setopt(curl, CURLOPT_POST, 1);
  34. //设置请求的URL地址
  35. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  36. //设置post请求的参数
  37. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str());
  38. //设置ssl验证
  39. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  40. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  41. //CURLOPT_VERBOSE的值为1时,会显示详细的调试信息
  42. curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
  43. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  44. //设置数据接收和写入函数
  45. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
  46. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
  47. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  48. //设置超时时间(单位:s)
  49. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
  50. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
  51. // 开启post请求
  52. res = curl_easy_perform(curl);
  53. }
  54. //释放curl
  55. curl_easy_cleanup(curl);
  56. return res;
  57. }
  58. void test_curl_post_req()
  59. {
  60. string url_post = "http://httpbin.org/post"; //设置URL
  61. Json::FastWriter writerinfo;
  62. Json::Value writevalueinfo;
  63. writevalueinfo["username"] = "000001";
  64. writevalueinfo["password"] = "123456";
  65. string paramsLogin = writerinfo.write(writevalueinfo); //设置post的json数据
  66. string resPost; //返回值
  67. auto res3 = curl_post_req(url_post, paramsLogin, resPost);
  68. if (res3 == CURLE_OK)
  69. {
  70. cout << resPost << endl;
  71. }
  72. }
  1. 打印结果如下:

五、其他

5.1 传递参数包含中文情况

  1. 一般地,本地端采用GBK编码方式,服务器端采用utf-8方式编码;当GET url参数含有中文字符时,除了设置utf8编码外,还需要对其额外进行特殊处理;
  1. string input; // 此处的input必须是utf-8编码格式
  2. // 对请求参数中的中文和特殊字符(如空格等)进行处理,方可使用
  3. char * escape_control = curl_escape(input.c_str(), input.size());
  4. input = escape_control;
  5. curl_free(escape_control);
  6. // 接下来就可以把input传入url了;

5.2 关于时间戳

​ 网络通信传输数据多见有时间戳属性,一并整理:

  1. // 日期转时间戳函数
  2. time_t convert_str_to_tm(const char * str_time)
  3. {
  4. struct tm tt;
  5. memset(&tt, 0, sizeof(tt));
  6. tt.tm_year = atoi(str_time) - 1900;
  7. tt.tm_mon = atoi(str_time + 5) - 1;
  8. tt.tm_mday = atoi(str_time + 8);
  9. tt.tm_hour = atoi(str_time + 11);
  10. tt.tm_min = atoi(str_time + 14);
  11. tt.tm_sec = atoi(str_time + 17);
  12. return mktime(&tt);
  13. }
  14. // 测试:日期转时间戳,再转为字符串
  15. string date = "2023-02-07 09:56:40";
  16. time_t timeStamp = convert_str_to_tm(date.c_str());
  17. std::string strTimeStamp = "";
  18. stringstream ss;
  19. ss << timeStamp;
  20. strTimeStamp = ss.str();
  21. cout << "Time Stamp:" << timeStamp<<"\t"<< strTimeStamp << endl;

六、参考链接

Visual Studio(VS2017/VS2019)编译并配置C/C++-libcurl开发环境

Visual Stdio2019下配置Libcurl的详细教程

Curl(C++)使用教程

C++使用curl发送get请求

C++使用curl发送post请求

C++使用CURL库POST请求向服务器发送JSON数据

C++ MFC 时间戳与日期格式相互转换

CTime 转 时间戳

标签: c++ http 网络协议

本文转载自: https://blog.csdn.net/weixin_44122235/article/details/128969128
版权归原作者 小火车1204 所有, 如有侵权,请联系我们删除。

“VS2019利用Curl库实现HTTP网络通信(C++)”的评论:

还没有评论