一、LibCurl基本編程框架
libcurl是一個跨平臺的網(wǎng)絡(luò)協(xié)議庫,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 協(xié)議。libcurl同樣支持HTTPS證書授權(quán),HTTP POST, HTTP PUT, FTP 上傳, HTTP基本表單上傳,代理,cookies,和用戶認(rèn)證。想要知道更多關(guān)于libcurl的介紹,可以到官網(wǎng) http://curl.haxx.se/上去了解,在這里不再詳述。 在基于LibCurl的程序里,主要采用callback function (回調(diào)函數(shù))的形式完成傳輸任務(wù),用戶在啟動傳輸前設(shè)置好各類參數(shù)和回調(diào)函數(shù),當(dāng)滿足條件時libcurl將調(diào)用用戶的回調(diào)函數(shù)實現(xiàn)特定功能。下面是利用libcurl完成傳輸任務(wù)的流程:
1. 調(diào)用curl_global_init()初始化libcurl
2. 調(diào)用curl_easy_init()函數(shù)得到 easy interface型指針
3. 調(diào)用curl_easy_setopt()設(shè)置傳輸選項
4. 根據(jù)curl_easy_setopt()設(shè)置的傳輸選項,實現(xiàn)回調(diào)函數(shù)以完成用戶特定任務(wù)
5. 調(diào)用curl_easy_perform()函數(shù)完成傳輸任務(wù)
6. 調(diào)用curl_easy_cleanup()釋放內(nèi)存
在整過過程中設(shè)置curl_easy_setopt()參數(shù)是最關(guān)鍵的,幾乎所有的libcurl程序都要使用它。
二、一些基本的函數(shù)
1.CURLcode curl_global_init(long flags);
描述:
這個函數(shù)只能用一次。(其實在調(diào)用curl_global_cleanup 函數(shù)后仍然可再用)
如果這個函數(shù)在curl_easy_init函數(shù)調(diào)用時還沒調(diào)用,它講由libcurl庫自動調(diào)用,所以多線程下最好主動調(diào)用該函數(shù)以防止在線程中curl_easy_init時多次調(diào)用。
注意:雖然libcurl是線程安全的,但curl_global_init是不能保證線程安全的,所以不要在每個線程中都調(diào)用curl_global_init,應(yīng)該將該函數(shù)的調(diào)用放在主線程中。
參數(shù):flags
CURL_GLOBAL_ALL //初始化所有的可能的調(diào)用。
CURL_GLOBAL_SSL //初始化支持 安全套接字層。
CURL_GLOBAL_WIN32 //初始化win32套接字庫。
CURL_GLOBAL_NOTHING //沒有額外的初始化。
2 void curl_global_cleanup(void);
描述:在結(jié)束libcurl使用的時候,用來對curl_global_init做的工作清理。類似于close的函數(shù)。
注意:雖然libcurl是線程安全的,但curl_global_cleanup是不能保證線程安全的,所以不要在每個線程中都調(diào)用curl_global_init,應(yīng)該將該函數(shù)的調(diào)用放在主線程中。
3 char *curl_version( );
描述: 打印當(dāng)前l(fā)ibcurl庫的版本。
4 CURL *curl_easy_init( );
描述:
curl_easy_init用來初始化一個CURL的指針(有些像返回FILE類型的指針一樣). 相應(yīng)的在調(diào)用結(jié)束時要用curl_easy_cleanup函數(shù)清理.
一般curl_easy_init意味著一個會話的開始. 它會返回一個easy_handle(CURL*對象), 一般都用在easy系列的函數(shù)中.
5 void curl_easy_cleanup(CURL *handle);
描述:
這個調(diào)用用來結(jié)束一個會話.與curl_easy_init配合著用.
參數(shù):
CURL類型的指針.
6 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
描述: 這個函數(shù)最重要了.幾乎所有的curl 程序都要頻繁的使用它.它告訴curl庫.程序?qū)⒂腥绾蔚男袨? 比如要查看一個網(wǎng)頁的html代碼等.(這個函數(shù)有些像ioctl函數(shù))參數(shù):
1 CURL類型的指針
2 各種CURLoption類型的選項.(都在curl.h庫里有定義,man 也可以查看到)
3 parameter 這個參數(shù) 既可以是個函數(shù)的指針,也可以是某個對象的指針,也可以是個long型的變量.它用什么這取決于第二個參數(shù).
CURLoption 這個參數(shù)的取值很多.具體的可以查看man手冊.
7 CURLcode curl_easy_perform(CURL *handle);
描述:這個函數(shù)在初始化CURL類型的指針 以及curl_easy_setopt完成后調(diào)用. 就像字面的意思所說perform就像是個舞臺.讓我們設(shè)置的
option 運(yùn)作起來.參數(shù):
CURL類型的指針.
三、 curl_easy_setopt函數(shù)部分選項介紹
本節(jié)主要介紹curl_easy_setopt中跟http相關(guān)的參數(shù)。該函數(shù)是curl中非常重要的函數(shù),curl所有設(shè)置都是在該函數(shù)中完成的,該函數(shù)的設(shè)置選項眾多,注意本節(jié)的闡述的只是部分常見選項。
1. CURLOPT_URL
設(shè)置訪問URL
2. CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
回調(diào)函數(shù)原型為:size_t function( void *ptr, size_t size, size_t nmemb, void *stream); 函數(shù)將在libcurl接收到數(shù)據(jù)后被調(diào)用,因此函數(shù)多做數(shù)據(jù)保存的功能,如處理下載文件。CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函數(shù)中的stream指針的來源。
如果你沒有通過CURLOPT_WRITEFUNCTION屬性給easy handle設(shè)置回調(diào)函數(shù),libcurl會提供一個默認(rèn)的回調(diào)函數(shù),它只是簡單的將接收到的數(shù)據(jù)打印到標(biāo)準(zhǔn)輸出。你也可以通過 CURLOPT_WRITEDATA屬性給默認(rèn)回調(diào)函數(shù)傳遞一個已經(jīng)打開的文件指針,用于將數(shù)據(jù)輸出到文件里。
3. CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
回調(diào)函數(shù)原型為 size_t function( void *ptr, size_t size,size_t nmemb, void *stream); libcurl一旦接收到http 頭部數(shù)據(jù)后將調(diào)用該函數(shù)。CURLOPT_WRITEDATA 傳遞指針給libcurl,該指針表明CURLOPT_HEADERFUNCTION 函數(shù)的stream指針的來源。
4. CURLOPT_READFUNCTION CURLOPT_READDATA
libCurl需要讀取數(shù)據(jù)傳遞給遠(yuǎn)程主機(jī)時將調(diào)用CURLOPT_READFUNCTION指定的函數(shù),函數(shù)原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函數(shù)原型中的stream指針來源。
5. CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
跟數(shù)據(jù)傳輸進(jìn)度相關(guān)的參數(shù)。CURLOPT_PROGRESSFUNCTION 指定的函數(shù)正常情況下每秒被libcurl調(diào)用一次,為了使CURLOPT_PROGRESSFUNCTION被調(diào)用,CURLOPT_NOPROGRESS必須被設(shè)置為false,CURLOPT_PROGRESSDATA指定的參數(shù)將作為CURLOPT_PROGRESSFUNCTION指定函數(shù)的第一個參數(shù)
6. CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
CURLOPT_TIMEOUT 由于設(shè)置傳輸時間,CURLOPT_CONNECTIONTIMEOUT 設(shè)置連接等待時間
7. CURLOPT_FOLLOWLOCATION
設(shè)置重定位URL
8. CURLOPT_RANGE: CURLOPT_RESUME_FROM:
斷點續(xù)傳相關(guān)設(shè)置。CURLOPT_RANGE 指定char *參數(shù)傳遞給libcurl,用于指明http域的RANGE頭域,例如:
表示頭500個字節(jié):bytes=0-499
表示第二個500字節(jié):bytes=500-999
表示最后500個字節(jié):bytes=-500
表示500字節(jié)以后的范圍:bytes=500-
第一個和最后一個字節(jié):bytes=0-0,-1
同時指定幾個范圍:bytes=500-600,601-999
CURLOPT_RESUME_FROM 傳遞一個long參數(shù)給libcurl,指定你希望開始傳遞的 偏移量。
四、 curl_easy_perform 函數(shù)說明(error 狀態(tài)碼)
該函數(shù)是完成curl_easy_setopt指定的所有選項,本節(jié)重點介紹curl_easy_perform的返回值。返回0意味一切ok,非0代表錯誤發(fā)生。主要錯誤碼說明:
1. CURLE_OK
任務(wù)完成一切都好
2 CURLE_UNSUPPORTED_PROTOCOL
不支持的協(xié)議,由URL的頭部指定
3 CURLE_COULDNT_CONNECT
不能連接到remote 主機(jī)或者代理
4 CURLE_REMOTE_ACCESS_DENIED
訪問被拒絕
5 CURLE_HTTP_RETURNED_ERROR
Http返回錯誤
6 CURLE_READ_ERROR
讀本地文件錯誤
要獲取詳細(xì)的錯誤描述字符串,可以通過const char *curl_easy_strerror(CURLcode errornum ) 這個函數(shù)取得.
五、libcurl使用的HTTP消息頭
當(dāng)使用libcurl發(fā)送http請求時,它會自動添加一些http頭。我們可以通過CURLOPT_HTTPHEADER屬性手動替換、添加或刪除相應(yīng) 的HTTP消息頭。
Host
http1.1(大部分http1.0)版本都要求客戶端請求提供這個信息頭。
Pragma
"no-cache"。表示不要緩沖數(shù)據(jù)。
Accept
"*/*"。表示允許接收任何類型的數(shù)據(jù)。
Expect
以POST的方式向HTTP服務(wù)器提交請求時,libcurl會設(shè)置該消息頭為"100-continue",它要求服務(wù)器在正式處理該請求之前,返回一 個"OK"消息。如果POST的數(shù)據(jù)很小,libcurl可能不會設(shè)置該消息頭。
自定義選項
當(dāng)前越來越多的協(xié)議都構(gòu)建在HTTP協(xié)議之上(如:soap),這主要?dú)w功于HTTP的可靠性,以及被廣泛使用的代理支持(可以穿透大部分防火墻)。 這些協(xié)議的使用方式與傳統(tǒng)HTTP可能有很大的不同。對此,libcurl作了很好的支持。
自定義請求方式(CustomRequest)
HTTP支持GET, HEAD或者POST提交請求??梢栽O(shè)置CURLOPT_CUSTOMREQUEST來設(shè)置自定義的請求方式,libcurl默認(rèn)以GET方式提交請求:
curl_easy_setopt(easy_handle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
修改消息頭
HTTP協(xié)議提供了消息頭,請求消息頭用于告訴服務(wù)器如何處理請求;響應(yīng)消息頭則告訴瀏覽器如何處理接收到的數(shù)據(jù)。在libcurl中,你可以自由的添加 這些消息頭:
struct curl_slist *headers=NULL; /* init to NULL is important */
headers = curl_slist_append(headers, "Hey-server-hey: how are you?");
headers = curl_slist_append(headers, "X-silly-content: yes");
/* pass our list of custom made headers */
curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
curl_easy_perform(easyhandle); /* transfer http */
curl_slist_free_all(headers); /* free the header list */
對于已經(jīng)存在的消息頭,可以重新設(shè)置它的值:
headers = curl_slist_append(headers, "Accept: Agent-007");
headers = curl_slist_append(headers, "Host: munged.host.line");
刪除消息頭
對于一個已經(jīng)存在的消息頭,設(shè)置它的內(nèi)容為空,libcurl在發(fā)送請求時就不會同時提交該消息頭:
headers = curl_slist_append(headers, "Accept:");
六、獲取http應(yīng)答頭信息
發(fā)出http請求后,服務(wù)器會返回應(yīng)答頭信息和應(yīng)答數(shù)據(jù),如果僅僅是打印應(yīng)答頭的所有內(nèi)容,則直接可以通過curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, 打印函數(shù))的方式來完成,這里需要獲取的是應(yīng)答頭中特定的信息,比如應(yīng)答碼、cookies列表等,則需要通過下面這個函數(shù):
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );
info參數(shù)就是我們需要獲取的內(nèi)容,下面是一些參數(shù)值:
1.CURLINFO_RESPONSE_CODE
獲取應(yīng)答碼
2.CURLINFO_HEADER_SIZE
頭大小
3.CURLINFO_COOKIELIST
cookies列表
除了獲取應(yīng)答信息外,這個函數(shù)還能獲取curl的一些內(nèi)部信息,如請求時間、連接時間等等。
更多的參數(shù)可以參考API文檔。
七、多線程問題
首先一個基本原則就是:絕對不應(yīng)該在線程之間共享同一個libcurl handle(CURL *對象),不管是easy handle還是multi handle(本文只介紹easy_handle)。一個線程每次只能使用一個handle。
libcurl是線程安全的,但有兩點例外:信號(signals)和SSL/TLS handler。 信號用于超時失效名字解析(timing out name resolves)。libcurl依賴其他的庫來支持SSL/STL,所以用多線程的方式訪問HTTPS或FTPS的URL時,應(yīng)該滿足這些庫對多線程 操作的一些要求。詳細(xì)可以參考:
OpenSSL: http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
GnuTLS: http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
NSS: 宣稱是多線程安全的。
八、什么時候libcurl無法正常工作
傳輸失敗總是有原因的。你可能錯誤的設(shè)置了一些libcurl的屬性或者沒有正確的理解某些屬性的含義,或者是遠(yuǎn)程主機(jī)返回一些無法被正確解析的內(nèi)容。
這里有一個黃金法則來處理這些問題:將CURLOPT_VERBOSE屬性設(shè)置為1,libcurl會輸出通信過程中的一些細(xì)節(jié)。如果使用的是http協(xié) 議,請求頭/響應(yīng)頭也會被輸出。將CURLOPT_HEADER設(shè)為1,這些頭信息將出現(xiàn)在消息的內(nèi)容中。
當(dāng)然不可否認(rèn)的是,libcurl還存在bug。
如果你對相關(guān)的協(xié)議了解越多,在使用libcurl時,就越不容易犯錯。
九、關(guān)于密碼
客戶端向服務(wù)器發(fā)送請求時,許多協(xié)議都要求提供用戶名與密碼。libcurl提供了多種方式來設(shè)置它們。
一些協(xié)議支持在URL中直接指定用戶名和密碼,類似于: protocol://user:[email protected]/path/。libcurl能正確的識別這種URL中的用戶名與密碼并執(zhí)行 相應(yīng)的操作。如果你提供的用戶名和密碼中有特殊字符,首先應(yīng)該對其進(jìn)行URL編碼。
也可以通過CURLOPT_USERPWD屬性來設(shè)置用戶名與密碼。參數(shù)是格式如 “user:password ”的字符串:
curl_easy_setopt(easy_handle, CURLOPT_USERPWD, "user_name:password");
有時候在訪問代理服務(wù)器的時候,可能時時要求提供用戶名和密碼進(jìn)行用戶身份驗證。這種情況下,libcurl提供了另 一個屬性CURLOPT_PROXYUSERPWD:
curl_easy_setopt(easy_handle, CURLOPT_PROXYUSERPWD, "user_name:password");
在UNIX平臺下,訪問FTP的用戶名和密碼可能會被保存在$HOME/.netrc文件中。libcurl支持直接從這個文件中獲取用戶名與密碼:
curl_easy_setopt(easy_handle, CURLOPT_NETRC, 1L);
在使用SSL時,可能需要提供一個私鑰用于數(shù)據(jù)安全傳輸,通過CURLOPT_KEYPASSWD來設(shè)置私鑰:
curl_easy_setopt(easy_handle, CURLOPT_KEYPASSWD, "keypassword");
十、HTTP驗證
在使用HTTP協(xié)議時,客戶端有很多種方式向服務(wù)器提供驗證信息。默認(rèn)的 HTTP驗證方法是"Basic”,它將用戶名與密碼以明文的方式、經(jīng)Base64編碼后保存在HTTP請求頭中,發(fā)往服務(wù)器。當(dāng)然這不太安全。
當(dāng)前版本的libcurl支持的驗證方法有:basic, Digest, NTLM, Negotiate, GSS-Negotiate and SPNEGO。(譯者感嘆:搞Web這么多年,盡然不知道這些Http的驗證方式,實在慚愧。)可以通過CURLOPT_HTTPAUTH屬性來設(shè)置具體 的驗證方式:
curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
向代理服務(wù)器發(fā)送驗證信息時,可以通過CURLOPT_PROXYAUTH設(shè)置驗證方式:
curl_easy_setopt(easy_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
也可以同時設(shè)置多種驗證方式(通過按位與), 使用‘CURLAUTH_ANY‘將允許libcurl可以選擇任何它所支持的驗證方式。通過CURLOPT_HTTPAUTH或 CURLOPT_PROXYAUTH屬性設(shè)置的多種驗證方式,libcurl會在運(yùn)行時選擇一種它認(rèn)為是最好的方式與服務(wù)器通信:
curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
// curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
應(yīng)用實例
- #ifndef __HTTP_CURL_H__
- #define __HTTP_CURL_H__
-
- #include <string>
-
- class CHttpClient
- {
- public:
- CHttpClient(void);
- ~CHttpClient(void);
-
- public:
-
-
-
-
-
-
-
- int Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse);
-
-
-
-
-
-
-
- int Get(const std::string & strUrl, std::string & strResponse);
-
-
-
-
-
-
-
-
-
- int Posts(const std::string & strUrl, const std::string & strPost, std::string & strResponse, const char * pCaPath = NULL);
-
-
-
-
-
-
-
-
- int Gets(const std::string & strUrl, std::string & strResponse, const char * pCaPath = NULL);
-
- public:
- void SetDebug(bool bDebug);
-
- private:
- bool m_bDebug;
- };
-
- #endif
具體實現(xiàn)的CPP
- #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)
- {
-
- }
- 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 size * 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);
- }
- 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);
- 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
- {
-
-
- 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;
- }