当使用C++做HTTP客户端时,目前通用的做法就是使用libcurl。其官方网站的地址是http://curl.haxx.se/,该网站主要提供了Curl和libcurl。Curl是命令行工具,用于完成FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP的命令的请求及接收回馈。libcurl提供给开发者,用于使用C++跨平台的开发各种网络协议的请求及响应。里面的文档非常齐全,不过都是英文的。

本文提供最简单的demo使用libcurl开发HttpClient。主要包括同步的HTTP GET、HTTP POST、HTTPS GET、HTTPS POST。

下载libcurl包,如果使用Linux平台,建议下载源文件编译;如果使用Windows平台,建议下载Win32 - MSVC,下载地址是:http://curl.haxx.se/download.html

  1. #ifndef __HTTP_CURL_H__
  2. #define __HTTP_CURL_H__
  3. #include <string>
  4. class CHttpClient
  5. {
  6. public:
  7. CHttpClient(void);
  8. ~CHttpClient(void);
  9. public:
  10. /**
  11. * @brief HTTP POST请求
  12. * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
  13. * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
  14. * @param strResponse 输出参数,返回的内容
  15. * @return 返回是否Post成功
  16. */
  17. int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);
  18. /**
  19. * @brief HTTP GET请求
  20. * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
  21. * @param strResponse 输出参数,返回的内容
  22. * @return 返回是否Post成功
  23. */
  24. int Get(const std::string & strUrl, std::string & strResponse);
  25. /**
  26. * @brief HTTPS POST请求,无证书版本
  27. * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
  28. * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
  29. * @param strResponse 输出参数,返回的内容
  30. * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
  31. * @return 返回是否Post成功
  32. */
  33. int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
  34. /**
  35. * @brief HTTPS GET请求,无证书版本
  36. * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
  37. * @param strResponse 输出参数,返回的内容
  38. * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
  39. * @return 返回是否Post成功
  40. */
  41. int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);
  42. public:
  43. void SetDebug(bool bDebug);
  44. private:
  45. bool m_bDebug;
  46. };
  47. #endif
  1. #include "httpclient.h"
  2. #include "curl/curl.h"
  3. #include <string>
  4. CHttpClient::CHttpClient(void) :
  5. m_bDebug(false)
  6. {
  7. }
  8. CHttpClient::~CHttpClient(void)
  9. {
  10. }
  11. static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
  12. {
  13. if(itype == CURLINFO_TEXT)
  14. {
  15. //printf("[TEXT]%s\n", pData);
  16. }
  17. else if(itype == CURLINFO_HEADER_IN)
  18. {
  19. printf("[HEADER_IN]%s\n", pData);
  20. }
  21. else if(itype == CURLINFO_HEADER_OUT)
  22. {
  23. printf("[HEADER_OUT]%s\n", pData);
  24. }
  25. else if(itype == CURLINFO_DATA_IN)
  26. {
  27. printf("[DATA_IN]%s\n", pData);
  28. }
  29. else if(itype == CURLINFO_DATA_OUT)
  30. {
  31. printf("[DATA_OUT]%s\n", pData);
  32. }
  33. return 0;
  34. }
  35. static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
  36. {
  37. std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
  38. if( NULL == str || NULL == buffer )
  39. {
  40. return -1;
  41. }
  42. char* pData = (char*)buffer;
  43. str->append(pData, size * nmemb);
  44. return nmemb;
  45. }
  46. int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
  47. {
  48. CURLcode res;
  49. CURL* curl = curl_easy_init();
  50. if(NULL == curl)
  51. {
  52. return CURLE_FAILED_INIT;
  53. }
  54. if(m_bDebug)
  55. {
  56. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  57. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  58. }
  59. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  60. curl_easy_setopt(curl, CURLOPT_POST, 1);
  61. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  62. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  63. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  64. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  65. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  66. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  67. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  68. res = curl_easy_perform(curl);
  69. curl_easy_cleanup(curl);
  70. return res;
  71. }
  72. int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)
  73. {
  74. CURLcode res;
  75. CURL* curl = curl_easy_init();
  76. if(NULL == curl)
  77. {
  78. return CURLE_FAILED_INIT;
  79. }
  80. if(m_bDebug)
  81. {
  82. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  83. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  84. }
  85. <pre name="code" class="cpp">   curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  86. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  87. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  88. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  89. /**
  90. * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
  91. * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
  92. */
  93. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  94. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  95. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  96. res = curl_easy_perform(curl);
  97. curl_easy_cleanup(curl);
  98. return res;
  99. }
  100. int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
  101. {
  102. CURLcode res;
  103. CURL* curl = curl_easy_init();
  104. if(NULL == curl)
  105. {
  106. return CURLE_FAILED_INIT;
  107. }
  108. if(m_bDebug)
  109. {
  110. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  111. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  112. }
  113. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  114. curl_easy_setopt(curl, CURLOPT_POST, 1);
  115. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  116. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  117. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  118. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  119. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  120. if(NULL == pCaPath)
  121. {
  122. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  123. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  124. }
  125. else
  126. {
  127. //缺省情况就是PEM,所以无需设置,另外支持DER
  128. //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
  129. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  130. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  131. }
  132. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  133. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  134. res = curl_easy_perform(curl);
  135. curl_easy_cleanup(curl);
  136. return res;
  137. }
  138. int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
  139. {
  140. CURLcode res;
  141. CURL* curl = curl_easy_init();
  142. if(NULL == curl)
  143. {
  144. return CURLE_FAILED_INIT;
  145. }
  146. if(m_bDebug)
  147. {
  148. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  149. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  150. }
  151. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  152. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  153. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  154. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  155. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  156. if(NULL == pCaPath)
  157. {
  158. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  159. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  160. }
  161. else
  162. {
  163. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  164. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  165. }
  166. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  167. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  168. res = curl_easy_perform(curl);
  169. curl_easy_cleanup(curl);
  170. return res;
  171. }
  172. ///////////////////////////////////////////////////////////////////////////////////////////////
  173. void CHttpClient::SetDebug(bool bDebug)
  174. {
  175. m_bDebug = bDebug;
  176. }
http://blog.csdn.net/huyiyang2010/article/details/7664201
 
当POST的内容为para=val,其中val包含'+'的时候会把'+'替换为' ',例如表单中有一项隐藏验证内容

  1. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNTc4MTM4MzMzZGQF+FxsPex77Sht1ZxPy5wLSXk1lpdzRqG9qS69Ybnkmg==" />

服务器收到的__VIEWSTATE值为

  1. <br>/wEPDwUJNTc4MTM4MzMzZGQF FxsPex77Sht1ZxPy5wLSXk1lpdzRqG9qS69Ybnkmg==<br>

不知道是不是本来就有这个BUG

Re: xiejienet 2013-12-23 01:03发表 [回复]
回复xingtianduiyue:post和get的数据,最好url编码

C++使用libcurl做HttpClient(业务观摩,用C++封装过程式代码,post和get的数据,最好url编码,否则+会变成空格)good的更多相关文章

  1. C++使用libcurl做HttpClient 和 curl_easy_setopt

    curl_easy_setopt 参数设置 https://curl.haxx.se/libcurl/c/curl_easy_setopt.html  使用libcurl做HttpClient #if ...

  2. vue各生命周期适合做的业务逻辑

    一.实际项目中使用最多的Vue生命周期大概是  created  mounted  updated 二.各自适合做的业务逻辑 1. created   相当于是页面刚开始加载的状态,此时不能操作实例的 ...

  3. 一步步教你为网站开发Android客户端---HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView

    本文面向Android初级开发者,有一定的Java和Android知识即可. 文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新List ...

  4. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(4)-业务逻辑层的封装

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(4)-业务逻辑层的封装 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2) ...

  5. Java HttpClient伪造请求之简易封装满足HTTP以及HTTPS请求

    HttpClient简介 HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 jav ...

  6. windows下openresty中使用lua做接口转发、二次封装等

    需求:根据客户需求,可以在ngx下 通过lua做接口二次封装再次转发给用户或第三方 场景:对返回值有要求的.接口屏蔽字段.或做一些业务上的验证等 1.windows直接下载openresty 解压即可 ...

  7. .NET应用架构设计—工作单元模式(摆脱过程式代码的重要思想,代替DDD实现轻量级业务)

    阅读目录: 1.背景介绍 2.过程式代码的真正困境 3.工作单元模式的简单示例 4.总结 1.背景介绍 一直都在谈论面向对象开发,但是开发企业应用系统时,使用面向对象开发最大的问题就是在于,多个对象之 ...

  8. httpclient模拟post请求json封装表单数据

    好长时间不更博了,主要肚子里没什么好墨水,哈哈.废话不说上代码. public static String httpPostWithJSON(String url) throws Exception ...

  9. 4.3.6 对象的界定通过编写接口来访问带这类命名结构的表会出问题。如前所述,SQL Server的灵活性不应用作编写错误代码或创建问题对象的借口。 注意在使用Management Studio的脚本工具时,SQL Server会界定所有的对象。这不是因为这么做是必须的,也不是编写代码的最佳方式,而是因为在界定符中封装所有的对象,比编写脚本引擎来查找需要界定的对象更容易。

    如前所述,在创建对象时,最好避免使用内嵌的空格或保留字作为对象名,但设计人员可能并没有遵守这个最佳实践原则.例如,我当前使用的数据库中有一个审核表名为Transaction,但是Transaction ...

随机推荐

  1. SocketChannel API用法

    java.nio.channels 类 SocketChannel java.lang.Object java.nio.channels.spi.AbstractInterruptibleChanne ...

  2. js进阶正则表达式修饰符(i、g、m)(var reg2=/html/gi)

    js进阶正则表达式修饰符(i.g.m)(var reg2=/html/gi) 一.总结 1.正则表达式使用:通过那些支持正则表达式的字符串函数来使用(search.match.replace.spli ...

  3. php实现把二叉树打印成多行(谋而后动,写好算法思路,不然浪费超多时间而且还是错误代码,而且精力消耗会导致代码正确率下降以及低级错误)

    php实现把二叉树打印成多行(谋而后动,写好算法思路,不然浪费超多时间而且还是错误代码,而且精力消耗会导致代码正确率下降以及低级错误) 一.总结 要点:a.层次遍历(队列)  b.层次遍历中的层次(孩 ...

  4. Opencv在视频中静态、动态方式绘制矩形框ROI

    Opencv视频处理中的目标跟踪经常用到要在视频上画一个矩形框ROI,标注出要跟踪的物体,这里介绍两种在视频中绘制矩形框的方法,一种是"静态的",一种是"动态的" ...

  5. Android自定义组件系列【3】——自定义ViewGroup实现侧滑

    有关自定义ViewGroup的文章已经很多了,我为什么写这篇文章,对于初学者或者对自定义组件比较生疏的朋友虽然可以拿来主义的用了,但是要一步一步的实现和了解其中的过程和原理才能真真脱离别人的代码,举一 ...

  6. Android java.lang.IllegalStateException: Already logged in to server.

    今晚在搞openfire时,无意中发现了这样的一个问题:问题描述: java.lang.IllegalStateException: Already logged in to server.原因:wh ...

  7. Kinect舒适区范围--UE4 的Blueprint测试范例

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接: http://blog.csdn.net/cartzhang/article/details/44748475 作者:ca ...

  8. xCode中怎样保存自己的代码块

    在开发iOS的过程中.xCode肯定是用得最多的工具.没有之中的一个.由于苹果官方提供的就这一个平台,尽管没有竞争对手,但秉承苹果一贯的注重细节的原则,xCode还是一款相当不错的IDE. 作为一名i ...

  9. Silverlight三维透视+倒影效果

    原文:Silverlight三维透视+倒影效果 知识概要: 1.使用2D内容创建3D体验,了解图像的PlaneProjection属性,具体内容读者自己查看文档. 2.Silverlight图形图形的 ...

  10. 百度UEditor上传图片-再再总结一次

    本周,CSDN有个网友遇到了百度UEditor上传问题,最后商定付50元钱,我帮他解决这个问题.    他最初想自己搞定这个问题,结果搞了好多次,好几天,还是没能解决.    2015年1月17日8: ...