libcurl入门之http通信(2)
1 摘要
1.1 平臺
運行平臺:君正x2000
libcurl版本:7.68.0,通過buildroot編譯生成。
編譯器:mips-linux-gnu-gcc (gcc version 7.2.0 (Ingenic r4.0.0-gcc720 2018.02-28))
編譯主機:ubuntu 18.04
?1.2 功能
http通信(1)
1.1最少的代碼實現http訪問百度,這個示例將通過get方法訪問百度,并將百度返回的結果存入data.html文件中。
http通信(2)
2.1 增加獲取libcurl庫信息
2.2 增加打印打印http響應head數據
2.3 增加使能版本庫調試功能
?2 打印版本庫信息
static void print_version_info(void) {curl_version_info_data *version_info = curl_version_info(CURLVERSION_NOW);printf("version:%s\n", version_info->version);printf("host:%s\n", version_info->host);printf("ssl_version:%s\n", version_info->ssl_version); }int main() {................/** 打印本本庫信息*/print_version_info();........return 0; }2.1 執行結果
# ./test version:7.68.0 host:mipsel-buildroot-linux-gnu ssl_version:OpenSSL/1.1.1g3 增加調試功能
CURLOPT_VERBOSE選項非常有用,當我們在調試嵌入式系統的時候沒有wireshark等抓包工具,打開CURLOPT_VERBOSE選項可以看到libcurl的執行過程
/** 設置libcurl的選項,沒有指定http訪問方法,libcurl默認使用get方法*/curl_easy_setopt(easy_handle, CURLOPT_URL, "http://www.baidu.com");curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, baidu_get_test_cb);curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fp);/** 增加調試功能,可以查看libcurl的執行過程*/curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1);3.1 執行結果
# ./test version:7.68.0 host:mipsel-buildroot-linux-gnu ssl_version:OpenSSL/1.1.1g * Trying 110.242.68.3:80... * TCP_NODELAY set * Connected to www.baidu.com (110.242.68.3) port 80 (#0) > GET / HTTP/1.1 Host: www.baidu.com Accept: */** Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Accept-Ranges: bytes < Cache-Control: no-cache < Connection: keep-alive < Content-Length: 14615 < Content-Type: text/html < Date: Sat, 20 Mar 2021 03:02:49 GMT < P3p: CP=" OTI DSP COR IVA OUR IND COM " < P3p: CP=" OTI DSP COR IVA OUR IND COM " < Pragma: no-cache < Server: BWS/1.1 < Set-Cookie: BAIDUID=948BD633A8A66E61E08D2D51C124E8F2:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com < Set-Cookie: BIDUPSID=948BD633A8A66E61E08D2D51C124E8F2; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com < Set-Cookie: PSTM=1616209369; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com < Set-Cookie: BAIDUID=948BD633A8A66E611382AE5374C312B9:FG=1; max-age=31536000; expires=Sun, 20-Mar-22 03:02:49 GMT; domain=.baidu.com; path=/; version=1; comment=bd < Traceid: 161620936935453114985383216040678206036 < Vary: Accept-Encoding < X-Ua-Compatible: IE=Edge,chrome=1 < * Connection #0 to host www.baidu.com left intact?
4 選項名:CURLOPT_HEADERFUNCTION?
CURLOPT_WRITEFUNCTION 用于接收http get返回的數據部分信息,如果想接收http get返回的頭部信息,可以使用CURLOPT_HEADERFUNCTION選項
4.1 原型
#include <curl/curl.h>
size_t header_callback(char *buffer, ? size_t size, ? size_t nitems, ? void *userdata);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERFUNCTION, header_callback);
4.2 描述
傳遞一個上面原型中類型的回調函數指針。
當libcurl接收頭數據的時候這個函數被調用。每一個頭部信息,都會調用一次這個函數并且只有完整的頭才會產生回調。使用這個函數去解析頭部是非常簡單的。buffer指針指向被接被接收的數據。nitems是數據的大小,size總是1。不要認為一行頭信息是以'\0'結束的。
userdata指針是你通過CURLOPT_HEADERDATA選項設置的。
回調函數必須返回實際被處理的字節個數,如果回調函數返回的和傳進來的字節數不同,libcurl將會產生一個錯誤信號。這將會引起傳輸終止,并且執行函數將會返回一個CURLE_WRITE_ERROR錯誤。
傳入到回到函數的完整的http可能多大CURL_MAX_HTTP_HEADER?(100K)字節數,這其中也包括最后一行含有的終止符。
重要的是要注意,在發起請求后,將為收到的所有響應的頭調用回調函數,而不僅僅是最終響應。這包括在身份驗證協商期間發生的所有響應。如果你只需要對最終響應的頭進行操作,那么您將需要自己在回調中收集頭信息,并使用HTTP狀態行來劃分響應邊界。
對于HTTP傳輸,狀態行和響應主體前面的空行都包含在報頭中,并傳遞給此函數。
5 代碼實實現
Makefile
LIBS=-L../../../buildroot/output/target/usr/lib -lpthread -lz -lcurl -lcrypto -lssl -lcjson CC_FLAG=-Wall -I../../../buildroot/output/staging/usr/include SRC=curl_test.c CC=mips-linux-gnu-gcc test : $(SRC)$(CC) $< $(LIBS) $(CC_FLAG) -O2 -o $@cp -v $@ ~/nfs.PHONY : cleanclean :rm -rf testcurl_test.c
#include <stdio.h> #include <curl/curl.h> #include <string.h> #include <time.h> #include <stdlib.h>static void baidu_get_test(void); static void print_version_info(void);int main() {CURLcode code;code = curl_global_init(CURL_GLOBAL_ALL);if(CURLE_OK != code) {printf("curl init Err\n");return -1;}/** 打印本本庫信息*/print_version_info();/** get 方法訪問百度并獲取數據*/baidu_get_test();curl_global_cleanup();return 0; }static size_t baidu_get_test_cb(void *buffer, size_t size, size_t nmemb, void *user_p) {FILE *fp = (FILE *)user_p;size_t return_size = fwrite(buffer, size, nmemb, fp);return return_size; }static size_t head_process_data(char *buffer, size_t size, size_t nitems, void *userdata) {char *head_line = userdata;printf("nitems = %d\n", nitems);strncpy(head_line, (const char *)buffer, nitems);*(head_line + nitems) = 0;printf("head info : %s", head_line);return nitems;}static void baidu_get_test(void) {/** 獲取一個easy句柄,后面通過這個句柄進行通信*/CURL *easy_handle = curl_easy_init();if(!easy_handle) {printf("curl_easy_init Err \n");curl_global_cleanup();return ;}/** 打開一個data.html文件,用于存儲百度返回的數據*/FILE *fp = fopen("data.html", "w+");char *head_line = (char *)malloc(100*1024);/** 設置libcurl的選項,沒有指定http訪問方法,libcurl默認使用get方法*/curl_easy_setopt(easy_handle, CURLOPT_URL, "http://www.baidu.com");curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, baidu_get_test_cb);curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fp);/** 增加調試功能,可以查看libcurl的執行過程*/curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1);/** 接收http頭信息*/curl_easy_setopt(easy_handle, CURLOPT_HEADERFUNCTION, head_process_data);curl_easy_setopt(easy_handle, CURLOPT_HEADERDATA, head_line);/** 執行訪問*/CURLcode code = curl_easy_perform(easy_handle);if(CURLE_OK != code) {printf("curl_easy_perform %d\n", code);}free(head_line);fclose(fp);/** 最后記得釋放句柄*/curl_easy_cleanup(easy_handle); }static void print_version_info(void) {curl_version_info_data *version_info = curl_version_info(CURLVERSION_NOW);printf("version:%s\n", version_info->version);printf("host:%s\n", version_info->host);printf("ssl_version:%s\n", version_info->ssl_version); }?
總結
以上是生活随笔為你收集整理的libcurl入门之http通信(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visualSVN Server的下载和
- 下一篇: Linux日常——端口