當使用C++做HTTP客戶端時,目前通用的做法就是使用libcurl,。其官方網(wǎng)站的地址是http://curl./,,該網(wǎng)站主要提供了Curl和libcurl。Curl是命令行工具,,用于完成FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP的命令的請求及接收回饋,。libcurl提供給開發(fā)者,用于使用C++跨平臺的開發(fā)各種網(wǎng)絡(luò)協(xié)議的請求及響應(yīng),。里面的文檔非常齊全,,不過都是英文的。
本文提供最簡單的demo使用libcurl開發(fā)HttpClient,。主要包括同步的HTTP GET,、HTTP POST、HTTPS GET,、HTTPS POST,。
下載libcurl包,如果使用Linux平臺,,建議下載源文件編譯,;如果使用Windows平臺,建議下載Win32 - MSVC,,下載地址是:http://curl./download.html
#ifndef __HTTP_CURL_H__ #define __HTTP_CURL_H__
#include <string>
class CHttpClient { public: CHttpClient(void); ~CHttpClient(void);
public: /** * @brief HTTP POST請求 * @param strUrl 輸入?yún)?shù),請求的Url地址,如:http://www.baidu.com * @param strPost 輸入?yún)?shù),使用如下格式para1=val1?2=val2&… * @param strResponse 輸出參數(shù),返回的內(nèi)容 * @return 返回是否Post成功 */ int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);
/** * @brief HTTP GET請求 * @param strUrl 輸入?yún)?shù),請求的Url地址,如:http://www.baidu.com * @param strResponse 輸出參數(shù),返回的內(nèi)容 * @return 返回是否Post成功 */ int Get(const std::string & strUrl, std::string & strResponse);
/** * @brief HTTPS POST請求,無證書版本 * @param strUrl 輸入?yún)?shù),請求的Url地址,如:https://www.alipay.com * @param strPost 輸入?yún)?shù),使用如下格式para1=val1?2=val2&… * @param strResponse 輸出參數(shù),返回的內(nèi)容 * @param pCaPath 輸入?yún)?shù),為CA證書的路徑.如果輸入為NULL,則不驗證服務(wù)器端證書的有效性. * @return 返回是否Post成功 */ int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
/** * @brief HTTPS GET請求,無證書版本 * @param strUrl 輸入?yún)?shù),請求的Url地址,如:https://www.alipay.com * @param strResponse 輸出參數(shù),返回的內(nèi)容 * @param pCaPath 輸入?yún)?shù),為CA證書的路徑.如果輸入為NULL,則不驗證服務(wù)器端證書的有效性. * @return 返回是否Post成功 */ int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);
public: void SetDebug(bool bDebug);
private: bool m_bDebug; };
#endif
[cpp] view plaincopy #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 name="code" class="cpp"> 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等操作。 * 如果不設(shè)置這個選項,,libcurl將會發(fā)信號打斷這個wait從而導(dǎo)致程序退出,。 */ 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,所以無需設(shè)置,另外支持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; }
|