C++使用libcurl做HttpClient

當使用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.   
  4. #include <string>  
  5.   
  6. class CHttpClient  
  7. {  
  8. public:  
  9.     CHttpClient(void);  
  10.     ~CHttpClient(void);  
  11.   
  12. public:  
  13.     /** 
  14.     * @brief HTTP POST請求 
  15.     * @param strUrl 輸入參數,請求的Url地址,如:http://www.baidu.com 
  16.     * @param strPost 輸入參數,使用如下格式para1=val1¶2=val2&… 
  17.     * @param strResponse 輸出參數,返回的內容 
  18.     * @return 返回是否Post成功 
  19.     */  
  20.     int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);  
  21.   
  22.     /** 
  23.     * @brief HTTP GET請求 
  24.     * @param strUrl 輸入參數,請求的Url地址,如:http://www.baidu.com 
  25.     * @param strResponse 輸出參數,返回的內容 
  26.     * @return 返回是否Post成功 
  27.     */  
  28.     int Get(const std::string & strUrl, std::string & strResponse);  
  29.   
  30.     /** 
  31.     * @brief HTTPS POST請求,無證書版本 
  32.     * @param strUrl 輸入參數,請求的Url地址,如:https://www.alipay.com 
  33.     * @param strPost 輸入參數,使用如下格式para1=val1¶2=val2&… 
  34.     * @param strResponse 輸出參數,返回的內容 
  35.     * @param pCaPath 輸入參數,爲CA證書的路徑.如果輸入爲NULL,則不驗證服務器端證書的有效性. 
  36.     * @return 返回是否Post成功 
  37.     */  
  38.     int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);  
  39.   
  40.     /** 
  41.     * @brief HTTPS GET請求,無證書版本 
  42.     * @param strUrl 輸入參數,請求的Url地址,如:https://www.alipay.com 
  43.     * @param strResponse 輸出參數,返回的內容 
  44.     * @param pCaPath 輸入參數,爲CA證書的路徑.如果輸入爲NULL,則不驗證服務器端證書的有效性. 
  45.     * @return 返回是否Post成功 
  46.     */  
  47.     int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);  
  48.   
  49. public:  
  50.     void SetDebug(bool bDebug);  
  51.   
  52. private:  
  53.     bool m_bDebug;  
  54. };  
  55.   
  56. #endif  

  1. #include "httpclient.h"  
  2. #include "curl/curl.h"  
  3. #include <string>  
  4.   
  5. CHttpClient::CHttpClient(void) :   
  6. m_bDebug(false)  
  7. {  
  8.   
  9. }  
  10.   
  11. CHttpClient::~CHttpClient(void)  
  12. {  
  13.   
  14. }  
  15.   
  16. static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)  
  17. {  
  18.     if(itype == CURLINFO_TEXT)  
  19.     {  
  20.         //printf("[TEXT]%s\n", pData);  
  21.     }  
  22.     else if(itype == CURLINFO_HEADER_IN)  
  23.     {  
  24.         printf("[HEADER_IN]%s\n", pData);  
  25.     }  
  26.     else if(itype == CURLINFO_HEADER_OUT)  
  27.     {  
  28.         printf("[HEADER_OUT]%s\n", pData);  
  29.     }  
  30.     else if(itype == CURLINFO_DATA_IN)  
  31.     {  
  32.         printf("[DATA_IN]%s\n", pData);  
  33.     }  
  34.     else if(itype == CURLINFO_DATA_OUT)  
  35.     {  
  36.         printf("[DATA_OUT]%s\n", pData);  
  37.     }  
  38.     return 0;  
  39. }  
  40.   
  41. static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)  
  42. {  
  43.     std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);  
  44.     if( NULL == str || NULL == buffer )  
  45.     {  
  46.         return -1;  
  47.     }  
  48.   
  49.     char* pData = (char*)buffer;  
  50.     str->append(pData, size * nmemb);  
  51.     return nmemb;  
  52. }  
  53.   
  54. int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)  
  55. {  
  56.     CURLcode res;  
  57.     CURL* curl = curl_easy_init();  
  58.     if(NULL == curl)  
  59.     {  
  60.         return CURLE_FAILED_INIT;  
  61.     }  
  62.     if(m_bDebug)  
  63.     {  
  64.         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
  65.         curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);  
  66.     }  
  67.     curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());  
  68.     curl_easy_setopt(curl, CURLOPT_POST, 1);  
  69.     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());  
  70.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
  71.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);  
  72.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);  
  73.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  74.     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);  
  75.     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
  76.     res = curl_easy_perform(curl);  
  77.     curl_easy_cleanup(curl);  
  78.     return res;  
  79. }  
  80.   
  81. int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)  
  82. {  
  83.     CURLcode res;  
  84.     CURL* curl = curl_easy_init();  
  85.     if(NULL == curl)  
  86.     {  
  87.         return CURLE_FAILED_INIT;  
  88.     }  
  89.     if(m_bDebug)  
  90.     {  
  91.         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
  92.         curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);  
  93.     }  
  94. <pre name="code" class="cpp">   curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());  
  95.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
  96.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);  
  97.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);  
  98.     /** 
  99.     * 當多個線程都使用超時處理的時候,同時主線程中有sleep或是wait等操作。 
  100.     * 如果不設置這個選項,libcurl將會發信號打斷這個wait從而導致程序退出。 
  101.     */  
  102.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  103.     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);  
  104.     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
  105.     res = curl_easy_perform(curl);  
  106.     curl_easy_cleanup(curl);  
  107.     return res;  
  108. }  
  109.   
  110. int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)  
  111. {  
  112.     CURLcode res;  
  113.     CURL* curl = curl_easy_init();  
  114.     if(NULL == curl)  
  115.     {  
  116.         return CURLE_FAILED_INIT;  
  117.     }  
  118.     if(m_bDebug)  
  119.     {  
  120.         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
  121.         curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);  
  122.     }  
  123.     curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());  
  124.     curl_easy_setopt(curl, CURLOPT_POST, 1);  
  125.     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());  
  126.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
  127.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);  
  128.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);  
  129.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  130.     if(NULL == pCaPath)  
  131.     {  
  132.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);  
  133.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);  
  134.     }  
  135.     else  
  136.     {  
  137.         //缺省情況就是PEM,所以無需設置,另外支持DER  
  138.         //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");  
  139.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);  
  140.         curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);  
  141.     }  
  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.   
  149. int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)  
  150. {  
  151.     CURLcode res;  
  152.     CURL* curl = curl_easy_init();  
  153.     if(NULL == curl)  
  154.     {  
  155.         return CURLE_FAILED_INIT;  
  156.     }  
  157.     if(m_bDebug)  
  158.     {  
  159.         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  
  160.         curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);  
  161.     }  
  162.     curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());  
  163.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);  
  164.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);  
  165.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);  
  166.     curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);  
  167.     if(NULL == pCaPath)  
  168.     {  
  169.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);  
  170.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);  
  171.     }  
  172.     else  
  173.     {  
  174.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);  
  175.         curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);  
  176.     }  
  177.     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);  
  178.     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);  
  179.     res = curl_easy_perform(curl);  
  180.     curl_easy_cleanup(curl);  
  181.     return res;  
  182. }  
  183.   
  184. ///////////////////////////////////////////////////////////////////////////////////////////////  
  185.   
  186. void CHttpClient::SetDebug(bool bDebug)  
  187. {  
  188.     m_bDebug = bDebug;  
  189. }  
  190. </pre><p></p>  
  191. <pre></pre>  
  192. <br>  
  193. <br>  
  194. <p></p>  
  195. <br>  
  196.       
  197.         <div style="padding-top:20px">           
  198.             <p style="font-size:12px;">版權聲明:本文爲博主原創文章,未經博主允許不得轉載。</p>  
  199.         </div>  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章