C++使用libcurl作HttpClient

 

原文來自:http://blog.csdn.net/huyiyang2010/article/details/7664201 轉載請註明html

 

當使用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.htmlapp

 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
#include "httpclient.h"
#include "curl/curl.h"
#include <string>

CHttpClient::CHttpClient(void) : 
m_bDebug(false)
{

}

CHttpClient::~CHttpClient(void)
{

}

static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
    if(itype == CURLINFO_TEXT)
    {
        //printf("[TEXT]%s\n", pData);
    }
    else if(itype == CURLINFO_HEADER_IN)
    {
        printf("[HEADER_IN]%s\n", pData);
    }
    else if(itype == CURLINFO_HEADER_OUT)
    {
        printf("[HEADER_OUT]%s\n", pData);
    }
    else if(itype == CURLINFO_DATA_IN)
    {
        printf("[DATA_IN]%s\n", pData);
    }
    else if(itype == CURLINFO_DATA_OUT)
    {
        printf("[DATA_OUT]%s\n", pData);
    }
    return 0;
}

static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
    std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
    if( NULL == str || NULL == buffer )
    {
        return -1;
    }

    char* pData = (char*)buffer;
    str->append(pData, size * nmemb);
    return nmemb;
}

int CHttpClient::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Get(const std::string & strUrl, std::string & strResponse)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
<PRE class=cpp name="code">    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    /**
    * 當多個線程都使用超時處理的時候,同時主線程中有sleep或是wait等操做。
    * 若是不設置這個選項,libcurl將會發信號打斷這個wait從而致使程序退出。
    */
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPost.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    if(NULL == pCaPath)
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else
    {
        //缺省狀況就是PEM,因此無需設置,另外支持DER
        //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

int CHttpClient::Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl)
    {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug)
    {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    if(NULL == pCaPath)
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else
    {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    return res;
}

///////////////////////////////////////////////////////////////////////////////////////////////

void CHttpClient::SetDebug(bool bDebug)
{
    m_bDebug = bDebug;
}
</PRE><P></P>
<PRE></PRE>
<BR>
<BR>
<P></P>
<BR>
相關文章
相關標籤/搜索