一、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)證。
libcurl的官網(wǎng):http://curl.haxx.se/
二、libcurl的使用
調(diào)用curl_global_init()初始化libcurl
調(diào)用curl_easy_init()函數(shù)得到 easy interface型指針
調(diào)用curl_easy_setopt()設(shè)置傳輸選項(xiàng)
根據(jù)curl_easy_setopt()設(shè)置的傳輸選項(xiàng),實(shí)現(xiàn)回調(diào)函數(shù)以完成用戶特定任務(wù)
調(diào)用curl_easy_perform()函數(shù)完成傳輸任務(wù)
調(diào)用curl_easy_cleanup()釋放內(nèi)存
三、libcurl等第三方庫的通用編譯方法
1.下載libcurl庫
庫下載:https://github.com/curl/curl/releases/tag/curl-7_71_1
2.下載好拖到ubuntu下解壓庫文件
tar xvf curl-7.71.1tar.bz2
2.解壓好后,進(jìn)去生成的文件目錄
后續(xù)學(xué)習(xí)需要用到的庫開源目錄包基本都長這樣,我們要看庫的使用說明文件README,或者docs目錄下的INSTALL,作者會告訴你怎么安裝使用庫。
3.找到UNIX環(huán)境安裝說明:
4.把庫的包開源包配置安裝在指定文件夾
./configure --prefix=$PWD/_install
配置完后,make編譯:
make
編譯完后,make install安裝拷貝:
make install
5.可以看到我們剛開始配置的文件夾_install,下載的庫就在lib目錄里面
xxx.a是靜態(tài)文件
xxx.so是動態(tài)文件
四、調(diào)用libcurl編程訪問百度主頁
1.先看具體實(shí)現(xiàn)代碼
#include <stdio.h>
#include <curl/curl.h>
#define true 1
#define false 0
typedef unsigned int bool; //把bool轉(zhuǎn)換成int類型,因?yàn)閏語言不支持bool類型
bool getUrl(char *filename)
{
CURL *curl;
CURLcode res;
FILE *fp;
if ((fp = fopen(filename, "w")) == NULL) // 返回結(jié)果用文件存儲
return false;
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Accept: Agent-007");
curl = curl_easy_init(); // 初始化
if (curl)
{
//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改協(xié)議頭
curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //將返回的http頭輸出到fp指向的文件
curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //將返回的html主體數(shù)據(jù)輸出到fp指向的文件
res = curl_easy_perform(curl); // 執(zhí)行
if (res != 0) {
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
fclose(fp);
return true;
}
}
/*
bool postUrl(char *filename)
{
CURL *curl;
CURLcode res;
FILE *fp;
if ((fp = fopen(filename, "w")) == NULL)
return false;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86"); // 指定post內(nèi)容
//curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi "); // 指定url
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
fclose(fp);
return true;
}
*/
int main(void)
{
getUrl("/tmp/get.html");
// postUrl("/tmp/post.html");
}
2.根據(jù)之前學(xué)習(xí)樹莓派的時候,靜態(tài)庫,動態(tài)庫那里。如果我們要調(diào)用庫的時候,要配置環(huán)境
:
僅該終端窗口有用,換個窗口程序就運(yùn)行不起來了。想要永久有效,就要把下面的配置 到 /home/free/.bashrc 文件下
export LD_LIBRARY_PATH=./curl-7.71.1/_install/lib
3.編譯運(yùn)行:
gcc demo1.c -I ./curl-7.71.1/_install/include/ -L ./curl-7.71.1/_install/lib/ -lcurl
-I ./curl-7.71.1/_install/include/表示將./curl-7.71.1/_install/include/目錄作為第一個尋找頭文件的目錄,尋找的順序是:./curl-7.71.1/_install/include/-->/usr/include-->/usr/local/include
-L ./curl-7.71.1/_install/lib/表示將./curl-7.71.1/_install/lib/目錄作為第一個尋找?guī)煳募哪夸?,尋找的順序是?span id="n5n3t3z" class="token punctuation">./curl-7.71.1/_install/lib/-->/lib-->/usr/lib-->/usr/local/lib
-lcurl 表示在上面的lib的路徑中尋找libcurl.so動態(tài)庫文件
運(yùn)行的結(jié)果已經(jīng)訪問到了百度,然后返回的數(shù)據(jù)保存在get.html文件里面,就不展示。
五、函數(shù)簡介
1 CURLcode curl_global_init(long flags);函數(shù)只能用一次。(其實(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類型的選項(xiàng).(都在curl.h庫里有定義,man 也可以查看到)
3)parameter 這個參數(shù) 既可以是個函數(shù)的指針,也可以是某個對象的指針,也可以是個long型的變量.它用什么這取決于第二個參數(shù).
CURLoption 這個參數(shù)的取值很多.具體的可以查看man手冊.
7 CURLcode curl_easy_perform(CURL *handle);
在初始化CURL類型的指針 以及curl_easy_setopt完成后調(diào)用. 就像字面的意思所說perform就像是個舞臺.讓我們設(shè)置的
option 運(yùn)作起來.參數(shù):
CURL類型的指針.
六、curl_easy_setopt函數(shù)部分選項(xiàng)介紹
本節(jié)主要介紹curl_easy_setopt中跟http相關(guān)的參數(shù)。該函數(shù)是curl中非常重要的函數(shù),curl所有設(shè)置都是在該函數(shù)中完成的,該函數(shù)的設(shè)置選項(xiàng)眾多,注意本節(jié)的闡述的只是部分常見選項(xiàng)。
-
CURLOPT_URL
設(shè)置訪問URL
-
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ù)輸出到文件里。
-
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指針的來源。
-
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指針來源。
-
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ù)
-
CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
CURLOPT_TIMEOUT 由于設(shè)置傳輸時間,CURLOPT_CONNECTIONTIMEOUT 設(shè)置連接等待時間
-
CURLOPT_FOLLOWLOCATION
設(shè)置重定位URL
-
CURLOPT_RANGE: CURLOPT_RESUME_FROM:
斷點(diǎn)續(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指定的所有選項(xiàng),本節(jié)重點(diǎn)介紹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
讀本地文件錯誤文章來源:http://www.zghlxwxcb.cn/news/detail-722739.html
要獲取詳細(xì)的錯誤描述字符串,可以通過const char *curl_easy_strerror(CURLcode errornum ) 這個函數(shù)取得.文章來源地址http://www.zghlxwxcb.cn/news/detail-722739.html
- 博文參考
到了這里,關(guān)于Linux基礎(chǔ)之HTTP協(xié)議之Libcurl的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!