分享

C++使用libcurl做HttpClient

 梦醉千秋 2015-06-17
当使用C++做HTTP客户端时,目前通用的做法就是使用libcurl。其官方网站的地址是http://curl./,该网站主要提供了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./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
  48. [cpp] view plaincopy
  49. #include "httpclient.h"
  50. #include "curl/curl.h"
  51. #include <string>
  52. CHttpClient::CHttpClient(void) :
  53. m_bDebug(false)
  54. {
  55. }
  56. CHttpClient::~CHttpClient(void)
  57. {
  58. }
  59. static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
  60. {
  61. if(itype == CURLINFO_TEXT)
  62. {
  63. //printf("[TEXT]%s\n", pData);
  64. }
  65. else if(itype == CURLINFO_HEADER_IN)
  66. {
  67. printf("[HEADER_IN]%s\n", pData);
  68. }
  69. else if(itype == CURLINFO_HEADER_OUT)
  70. {
  71. printf("[HEADER_OUT]%s\n", pData);
  72. }
  73. else if(itype == CURLINFO_DATA_IN)
  74. {
  75. printf("[DATA_IN]%s\n", pData);
  76. }
  77. else if(itype == CURLINFO_DATA_OUT)
  78. {
  79. printf("[DATA_OUT]%s\n", pData);
  80. }
  81. return 0;
  82. }
  83. static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
  84. {
  85. std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
  86. if( NULL == str || NULL == buffer )
  87. {
  88. return -1;
  89. }
  90. char* pData = (char*)buffer;
  91. str->append(pData, size * nmemb);
  92. return nmemb;
  93. }
  94. int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
  95. {
  96. CURLcode res;
  97. CURL* curl = curl_easy_init();
  98. if(NULL == curl)
  99. {
  100. return CURLE_FAILED_INIT;
  101. }
  102. if(m_bDebug)
  103. {
  104. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  105. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  106. }
  107. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  108. curl_easy_setopt(curl, CURLOPT_POST, 1);
  109. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  110. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  111. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  112. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  113. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  114. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  115. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  116. res = curl_easy_perform(curl);
  117. curl_easy_cleanup(curl);
  118. return res;
  119. }
  120. int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)
  121. {
  122. CURLcode res;
  123. CURL* curl = curl_easy_init();
  124. if(NULL == curl)
  125. {
  126. return CURLE_FAILED_INIT;
  127. }
  128. if(m_bDebug)
  129. {
  130. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  131. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  132. }
  133. <pre name="code" class="cpp"> curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  134. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  135. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  136. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  137. /**
  138. * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
  139. * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
  140. */
  141. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  142. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  143. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  144. res = curl_easy_perform(curl);
  145. curl_easy_cleanup(curl);
  146. return res;
  147. }
  148. int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
  149. {
  150. CURLcode res;
  151. CURL* curl = curl_easy_init();
  152. if(NULL == curl)
  153. {
  154. return CURLE_FAILED_INIT;
  155. }
  156. if(m_bDebug)
  157. {
  158. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  159. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  160. }
  161. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  162. curl_easy_setopt(curl, CURLOPT_POST, 1);
  163. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
  164. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  165. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  166. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  167. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  168. if(NULL == pCaPath)
  169. {
  170. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  171. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  172. }
  173. else
  174. {
  175. //缺省情况就是PEM,所以无需设置,另外支持DER
  176. //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
  177. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  178. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  179. }
  180. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  181. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  182. res = curl_easy_perform(curl);
  183. curl_easy_cleanup(curl);
  184. return res;
  185. }
  186. int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
  187. {
  188. CURLcode res;
  189. CURL* curl = curl_easy_init();
  190. if(NULL == curl)
  191. {
  192. return CURLE_FAILED_INIT;
  193. }
  194. if(m_bDebug)
  195. {
  196. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  197. curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
  198. }
  199. curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
  200. curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
  201. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
  202. curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
  203. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  204. if(NULL == pCaPath)
  205. {
  206. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
  207. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
  208. }
  209. else
  210. {
  211. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
  212. curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
  213. }
  214. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
  215. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
  216. res = curl_easy_perform(curl);
  217. curl_easy_cleanup(curl);
  218. return res;
  219. }
  220. ///////////////////////////////////////////////////////////////////////////////////////////////
  221. void CHttpClient::SetDebug(bool bDebug)
  222. {
  223. m_bDebug = bDebug;
  224. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约