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