libcurl学习
libcurl是C語言開發(fā)的網(wǎng)絡(luò)庫,支持多種網(wǎng)絡(luò)協(xié)議。
libcurl是一個跨平臺的開源網(wǎng)絡(luò)協(xié)議庫,支持http,https,rstp等多種協(xié)議。ibcurl同樣支持HTTPS證書授權(quán),HTTP POST,HTTP PUT,FTP上傳,HTTP基本表單上傳,代理,cookies,用戶認(rèn)證。
Curl提供了一系列接口,可分為easy interface和multinterface,前者是阻塞的,后者可用于多線程,可做非阻塞應(yīng)用。兩者不是獨立的,multi interface也依賴于easy interface。
Easy interface
初始化/清理curl環(huán)境 curl_global_init/curl_global_cleanup初始化/釋放easy handle curl_easy_init/curl_easy_cleanup設(shè)url curl_easy_setop(easy_handle_,CURLOPT_URL,"http://www.xxx.com/RL.do");設(shè)HTTP方法 POST curl_easy_setopt(easy_handle_,CURLOPT_POST,1);GET curl_easy_setop(easy_handle_,CURLOPT_HTTPGET,1);PUT curl_easy_setopt(easy_handele_,CURLOPT_UPLOAD,1);POST multipart/formdata類型 curl_easy_setopt(easy_handle_,CURLOPT_HTTPOST,formpost);設(shè)body curl_easy_setopt(easy_handle_,CURLOPT_poSTFIELDS,body.c_str());設(shè)置超時時間,10s內(nèi)數(shù)據(jù)接收未完成則直接退出 curl_easy_setop(easy_handle_,CURLOPT_TIMEOUT, 10);設(shè)置User-Agent curl_easy_setopt(easy_handele_,CURLOPT_USERAGENT,"XXX");接收數(shù)據(jù),輸入類的靜態(tài)函數(shù)地址 curl_easy_setopt(easy_handle_,CURLOPT_WRITEFUNCTION,&RecvDAta); curl_easy_setopt(easy_handle_,CURLOPT_WRITEDATA,this);執(zhí)行 curl_easy_perform(easy_handle_);取得redirect url curl_easy_getinfo(easy_handle_,CURLINFO_REDIRECT_URL,&redirect_url);取得cookies,若要取得某一cookie值,需解析 curl_easy_getinfo(easy_handle_,CURLINFO_COOKIELIST, &cookies)取得response code curl_easy_getinfo(easy_handle_,CURLINFO_RESPONSE_CODE, &res_code_);cookie操作設(shè)置客戶端接收到的cookie的存放目錄curl_easy_setopt(easy_handle_, CURLOPT_COOKIEJAR, cookie_file_.c_str());設(shè)置讀取的cookie文件curl_easy_setopt(easy_handle_, CURLOPT_COOKIEFILE, cookie_file_.c_str());上傳文件方法一:傳入文件路徑,不需要寫讀文件內(nèi)容的代碼curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME, "photos",CURLFORM_FILE, utf8_file_name.c_str(), // 文件路徑CURLFORM_END);方法二:先將文件內(nèi)容讀入內(nèi)存,將內(nèi)容傳入curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME, "photos",CURLFORM_BUFFER, "a.jpg",CURLFORM_BUFFERPTR, file_data,CURLFORM_BUFFERLENGTH, file_size,CURLFORM_CONTENTTYPE, "image/jpeg",CURLFORM_END);url-encode/url-decodecurl_escape、curl_unescape、curl_freeEXP:
1.初始化,這個函數(shù)必須是調(diào)用的第一個函數(shù),并且返回一個easy interface的handle,使用該handle作為easy接口中其他函數(shù)的輸入。
CURL *curl_easy_init();2.當(dāng)操作完成時,此調(diào)用必須有相應(yīng)的調(diào)用curl_easy_cleanup()來釋放handle。
void curl_easy_cleanup(CURL *handle);3.設(shè)置此次傳輸?shù)囊恍┗緟?shù),如url地址、http頭、cookie信息、發(fā)送超時時間等,其中,CURLOPT_URL是必設(shè)的選項。該函數(shù)是整個模塊的核心,使用該函數(shù),我們可以設(shè)置很多相關(guān)操作,正是由于該函數(shù)的存在,才另libcurl變得簡單且具備多種可操作性。
curl_easy_setpot一些經(jīng)常使用的方式,會在后面補充
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parametr);4.在上述準(zhǔn)備工作已經(jīng)完成后,可以調(diào)用curl_easy_perform函數(shù),則會開始HTTP的請求工作。該接口是一個阻塞的接口。
CURLcode curl_easy_perform(CURL *easy_handle);5.請求過程中,可以使用下面函數(shù),獲取HTTP該次請求的相關(guān)信息,包括response code,下載的URL,下載速度等。該函數(shù)對于一次請求不是必須的。
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);第二個參數(shù)有眾多選項,每個選項都有其相應(yīng)的含義,第三個參數(shù)根據(jù)參數(shù)2,會有不同的類型。常用的info如下:
1、CURLINFO_RESPONSE_CODE 取得response code,要求第 3 個參數(shù)是個 long
型的指針。如果TCP就連接不上,值為0。 CURLINFO_EFFECTIVE_URL
取得本最終生效的URL,也即是如果有多次重定向,獲取的值為最后一次URL,要求第 3 個參數(shù)是個 char 型的指針。
2、CURLINFO_SIZE_DOWNLOAD 獲取下載字節(jié)數(shù),要求第 3 個參數(shù)是個 double
型的指針。注意,這個字節(jié)數(shù)只能反映最近一次的下載。
3、CURLINFO_SPEED_DOWNLOAD 獲取平均下載數(shù)據(jù),該選項要求傳遞一個
double 型參數(shù)指針,這個速度不是即時速度,而是下載完成后的速度,單位是 字節(jié)/秒
4、CURLINFO_TOTAL_TIME
獲取傳輸總耗時,要求傳遞一個 double 指針到函數(shù)中,這個總的時間里包括了域名解析,以及 TCP 連接過程中所需要的時間。
5、CURLINFO_CONTENT_TYPE 該選項獲得 HTTP 中從服務(wù)器端收到的頭部中的 Content-Type 信息。
6、CURLINFO_CONTENT_LENGTH_DOWNLOAD 獲取頭部content-length,要求第 3 個參數(shù)是個 double
型的指針。如果文件大小無法獲取,那么函數(shù)返回值為 -1 。
curl_easy_setopt簡介:
函數(shù)原型:
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);描述:
這個函數(shù)幾乎所有的curl程序都要頻繁的使用它,它告訴curl庫程序?qū)⒂腥绾蔚男袨椤?#xff08;這個函數(shù)類似ioctl函數(shù))
參數(shù):
1CURL類型的指針
2各種CURLoption類型的選項。這個參數(shù)的取值很多,具體可以查看man手冊。
3.parameter這個參數(shù)既可以是個函數(shù)的指針,也可以是某個對象的指針,也可以是個long類型的變量,它用什么取決于第二個參數(shù)。
下面介紹幾個常用的參數(shù)及使用方法:
1.CURLOPT_URL這個選項必須要有,設(shè)置請求的URL,如果URL參數(shù)不寫上協(xié)議頭(如“http://”或者“ftp://”等等),那么函數(shù)會自己進(jìn)行猜解所給的主機(jī)上用的是哪一種服務(wù)協(xié)議。 假如給的這個地址是一個不被支持的協(xié)議,那么在其后執(zhí)行curl_easy_perform()函數(shù)或curl_multi_perform()調(diào)用時,libcurl將返回錯誤(CURL_UNSUPPORTED_PROTOCOL).這個選項時唯一一個在curl_easy_perform()調(diào)用之前就一定要設(shè)置的選項。2.CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA 1)CURLOPT_WRITEFUNCTION選項用于設(shè)置接收數(shù)據(jù)回掉函數(shù),回掉函數(shù)原型為:size_t function(coid *ptr, size_t size,size_t nmemb, void *stream);函數(shù)將在libcurl接收到數(shù)據(jù)后被調(diào)用,因此函數(shù)多做數(shù)據(jù)保存的功能,如處理下載文件。 2)CURLOPT_WAITEDATA選項用于指定CURLOPT_WRITEFUNCTION函數(shù)中的stream指針來源。 3)如果沒有通過CURLOPT_WRITEFUNCTION屬性給easy handle設(shè)置回調(diào)函數(shù),libcurl會提供一個默認(rèn)的回掉函數(shù),它只是簡單的將接收到的數(shù)據(jù)打印到標(biāo)準(zhǔn)輸出。也可以通過CURLOPT_WRITEDATA屬性給默認(rèn)回掉函數(shù)傳遞一個已經(jīng)打開的文件指針,用于將數(shù)據(jù)輸出到文件里。3.CURLOPT_HEADERFUNCTION, CURLOPT_HEADERDATA 1)CURLOPT_HEADERFUNCTION設(shè)置接收到http頭的回調(diào)函數(shù),原型為:size_t function(void *ptr,size_t size, size_t nmemb, void *stream);libcurl一旦接收到http 頭部數(shù)據(jù)后將調(diào)用該函數(shù)。2)CURLOPT_HEADERDATA傳遞指針給libcurl,該指針表明CURLOPT_HEADERFUNCTION函數(shù)的strean指針的來源。和上面兩組類似的,這樣對應(yīng)的回調(diào)選項還有很多,使用方法也類似,如: CURLOPT_READFUNCTION/ CURLOPT_READDATA;
CURLOPT_HTTPHEADER
libcurl有自己默認(rèn)的請求頭,如果不符合我們的要求,可以使用該選項自定義請求頭。可以使用curl_slist_append進(jìn)行自定義,重設(shè),如果設(shè)置請求參數(shù)為空,則相當(dāng)于刪除該請求頭。
CURLOPT_USERAGENT
該選項要求傳遞一個以 ‘\0’ 結(jié)尾的字符串指針,這個字符串用來在向服務(wù)器請求時發(fā)送 HTTP 頭部中的 User-Agent 信息,有些服務(wù)器是需要檢測這個信息的,如果沒有設(shè)置User-Agent,那么服務(wù)器拒絕請求。設(shè)置后,可以騙過服務(wù)器對此的檢查。
CURLOPT_VERBOSE
在使用該選項且第 3 個參數(shù)為 1 時,curl 庫會顯示詳細(xì)的操作信息。這對程序的調(diào)試具有極大的幫助。
CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
這三個選項和跟數(shù)據(jù)傳輸進(jìn)度相關(guān)。
1)CURLOPT_PROGRESSFUNCTION設(shè)置回調(diào)函數(shù),函數(shù)原型: int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); progress_callback正常情況下每秒被libcurl調(diào)用一次。
2)CURLOPT_NOPROGRESS必須被設(shè)置為false才會啟用該功能,
3)CURLOPT_PROGRESSDATA指定的參數(shù)將作為CURLOPT_PROGRESSFUNCTION指定函數(shù)的第一個參數(shù)。
CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT
超時相關(guān)設(shè)置,時間單位為s
1)CURLOPT_TIMEOUT設(shè)置整個libcurl傳輸超時時間。
2)CURLOPT_CONNECTIONTIMEOUT
設(shè)置連接等待時間。設(shè)置為0,則無限等待。
CURLOPT_FOLLOWLOCATION,CURLOPT_MAXREDIRS
重定向相關(guān)設(shè)置
1)CURLOPT_FOLLOWLOCATION 設(shè)置為非0,響應(yīng)頭信息Location,即curl會自己處理302等重定向
2)CURLOPT_MAXREDIRS指定HTTP重定向的最大次數(shù)
CURLOPT_RANGE ,CURLOPT_RESUME_FROM/ CURLOPT_RESUME_FROM_LARGE 斷點續(xù)傳相關(guān)設(shè)置。
1)CURLOPT_RANGE 指定char *參數(shù)傳遞給libcurl,用于指明http請求的range
2)CURLOPT_RESUME_FROM傳遞一個long參數(shù)作為偏移量給libcurl,指定開始進(jìn)行傳輸?shù)奈恢谩URLOPT_RESUME_FROM大小限制為2G,超過可以使用CURLOPT_RESUME_FROM_LARGE
CURLOPT_POSTFIELDS,CURLOPT_POSTFIELDSIZE
1)CURLOPT_POSTFIELDS 傳遞一個作為HTTP “POST”操作的所有數(shù)據(jù)的字符串。
2)CURLOPT_POSTFIELDSIZE 設(shè)置POST 字節(jié)大小。
CURLOPT_NOBODY
設(shè)置該屬性即可告訴libcurl我想發(fā)起一個HEAD請求 有時候你想查詢服務(wù)器某種資源的狀態(tài),比如某個文件的屬性:修改時間,大小等等,但是并不需要具體得到該文件,這時我們僅需要HEAD請求。
CURLOPT_ACCEPT_ENCODING
設(shè)置libcurl對特定壓縮方式自動解碼,支持的方式有: “br, gzip, deflate”. 第3個參數(shù)為指定的壓縮方式,如果設(shè)置為 " ",則表明三種都支持。
CURLOPT_MAX_RECV_SPEED_LARGE,CURLOPT_MAX_SEND_SPEED_LARGE
限速相關(guān)設(shè)置
1)CURLOPT_MAX_RECV_SPEED_LARGE,指定下載過程中最大速度,單位bytes/s。
2)CURLOPT_MAX_SEND_SPEED_LARG,指定上傳過程中最大速度,單位bytes/s。
CURLOPT_FORBID_REUSE ,CURLOPT_FRESH_CONNEC
如果不使用長連接,需要設(shè)置這兩個屬性
1)CURLOPT_FORBID_REUSE 設(shè)置為1,在完成交互以后強(qiáng)迫斷開連接,不重用。
2)CURLOPT_FRESH_CONNECT設(shè)置為1,強(qiáng)制獲取一個新的連接,替代緩存中的連接。
CURLOPT_NOSIGNAL
當(dāng)多個線程都使用超時處理的時候,同時主線程中有sleep或是wait等操作。如果不設(shè)置這個選項,libcurl將會發(fā)信號打斷這個wait從而可能導(dǎo)致程序crash。 在多線程處理場景下使用超時選項時,會忽略signals對應(yīng)的處理函數(shù)。
CURLOPT_BUFFERSIZE
指定libcurl中接收緩沖區(qū)的首選大小(以字節(jié)為單位),但是不保證接收數(shù)據(jù)時每次數(shù)據(jù)量都能達(dá)到這個值。此緩沖區(qū)大小默認(rèn)為CURL_MAX_WRITE_SIZE(16kB)。允許設(shè)置的最大緩沖區(qū)大小為CURL_MAX_READ_SIZE(512kB)。 允許設(shè)置的最小緩沖區(qū)大小為1024。
multi interface使用方法
multi interface的使用是在easy interface的基礎(chǔ)之上,將多個easy handler加入到一個stack中,同時發(fā)送請求。與easy interface不同,它是一種異步,非阻塞的傳輸方式。
在掌握easy interface的基礎(chǔ)上,multi interface的使用也很簡單:
1)curl_multi _init初始化一個multi handler對象,
2)初始化多個easy handler對象,使用curl_easy_setopt進(jìn)行相關(guān)設(shè)置,
3)調(diào)用curl_multi _add_handle把easy handler添加到multi curl對象中
4)添加完畢后執(zhí)行curl_multi_perform方法進(jìn)行并發(fā)的訪問,
5)訪問結(jié)束后curl_multi_remove_handle移除相關(guān)easy curl對象,先用curl_easy_cleanup清除easy handler對象,最后curl_multi_cleanup清除multi handler對象。
multi interface一些函數(shù)說明:
和easy interface類似,multi 的初始化和清除函數(shù)如下:
CURLM curl_multi_init( );
CURLMcode curl_multi_cleanup( CURLMmulti_handle );
CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);
當(dāng)設(shè)置好easy模式并準(zhǔn)備傳輸?shù)臅r候,可以使用curl_multi_add_handle替代curl_easy_perform,這樣easy handler則會加入multi棧中。我們能在任何時候增加一個esay handler給multi模式,即使easy已經(jīng)在執(zhí)行傳輸操作了。
也可以在任何時候使用curl_multi_remove_handle將esay handler從multi棧中移出,一旦移出可以再次使用curl_easy_perform來進(jìn)行傳輸任務(wù)。
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);
添加easy handler到multi并不馬上開始執(zhí)行,由curl_multi_perform啟動執(zhí)行。
啟動后將執(zhí)行所有multi stack中的收發(fā)事件。如果棧上是空的直接返回。函數(shù)參數(shù)running_handles會返回當(dāng)前還未結(jié)束的easy handler個數(shù)。
等待及超時
CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
CURLMcode curl_multi_wait(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *numfds);
libcurl中,舊的API使用curl_multi_fdset設(shè)置 select或者poll模型觸發(fā)。
總結(jié)
- 上一篇: 智慧灯杆应用:京东智慧路灯亮相雄安,可完
- 下一篇: hashcode值指的是什么_哈希码值是