当使用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. }

    image.jpeg