日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页

發(fā)布時間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文為學(xué)習(xí)筆記,整合課程內(nèi)容以及下列文章:

其中,libcurl函數(shù)庫常用字段解讀部分:

參考博文:原文地址
作者:冬冬他哥哥

目錄

  • Libcurl庫簡介
  • Libcurl等三方庫的通用編譯方法
    • 三方庫使用前通讀方法
    • 庫的配置、編譯、安裝
  • 調(diào)用libcurl編程訪問百度主頁
    • 代碼
    • 編譯注意(編譯時鏈接庫、頭文件路徑,運(yùn)行需添加動態(tài)庫為環(huán)境變量)
  • libcurl函數(shù)庫常用字段解讀
    • 1.curl_global_init():初始化libcurl
    • 2.curl_easy_init():拿到句柄
    • 3.curl_easy_setopt(CURL *handle, CURLoption option, parameter):設(shè)置傳輸選項(xiàng)
    • 4.curl_easy_perform():執(zhí)行任務(wù)
    • 5.curl_easy_cleanup():釋放內(nèi)存
  • 往期文章

Libcurl庫簡介

在linux下用c語言做HTTP的編程有一種方法是依賴于這個libcurl庫,以后做跨平臺網(wǎng)絡(luò)協(xié)議相關(guān)的開發(fā),第一個要想到的就是它。

libcurl是一個跨平臺的網(wǎng)絡(luò)協(xié)議庫,支持http, https, ftp等協(xié)議,libcurl同樣支持:

(1)HTTPS證書授權(quán)
(2)HTTP POST, HTTP PUT, FTP 上傳
(3) HTTP基本表單上傳,代理,cookies,和用戶認(rèn)證

庫下載地址:庫下載

然后發(fā)送到linux開發(fā)環(huán)境中。

Libcurl等三方庫的通用編譯方法

三方庫使用前通讀方法

解壓下載的庫

tar xvf curl-7.71.1.tar.bz2

進(jìn)入文件夾

cd curl-7.71.1

對于這種開源的包,一定要學(xué)會它的使用:

先看README:

vi README

并沒有發(fā)現(xiàn)一些特別有用的東西。


沒關(guān)系,去看這個

docs文件夾很重要,一般是對README的補(bǔ)充

cd docs

不需要看太多,看類似于這個:前面README提到的相關(guān)的API手冊

vi curl.1

也很難受,真提取不到什么信息。

嵌入式開發(fā)變得簡單了是因?yàn)榍度胧浇?jīng)過十幾二十年的發(fā)展有很多人對其進(jìn)行解讀,寫了很多文章。

重點(diǎn)是看INSTALL文件

還是重點(diǎn)來看看docs下的INSTALL文件,庫一定要學(xué)會安裝才能使用。


臥槽,外國人在繞圈圈,大概看看INSTALL.md

可以看到./configure后面沒有跟任何參數(shù)就是默認(rèn)安裝位置了,這里我們肯定要做配置,不配置都不知道文件安裝到哪里去了

make就是編譯的意思
make install就是把編譯的結(jié)果拷貝到根的指定文件夾底下

關(guān)于幫助:
不在原本默認(rèn)的路徑下安裝說明:

配置是否支持https:

回到/curl-7.71.1目錄下,configure --help看看

./configure --help

[注意]help前不用加空格,我加了反而顯示不了幫助信息了。

可以看到上文所提及的安裝路徑配置:

也可以看到特別重要的交叉編譯說明:

庫的配置、編譯、安裝

(1)安裝位置的更改:

配置為:$獲取當(dāng)前路徑,編譯的時候會自動生成_install文件夾,并且把編譯生成的東西全部放入這個文件夾。

./configure --prefix=$PWD/_install

另外,這是針對于交叉編譯的配置:編譯后在樹莓派上用
./configure --prefix=$PWD/_install --host=arm-linux
這樣,在ubuntu中就會使用arm-gcc進(jìn)行編譯

如果上述操作直接在樹莓派上進(jìn)行,則不用再去額外配置交叉編譯。工作中開發(fā)板往往沒有編譯工具,需要在上位機(jī)上進(jìn)行編譯,那么這里就要進(jìn)行交叉編譯配置。

(2)開始編譯

make

(3)安裝

make install

(4)預(yù)覽

進(jìn)入 /_install

我們用的是頭文件

cd include

進(jìn)入里面的這個

cd curl

這些都是要用到的頭文件
就像樹莓派編譯是要鏈接庫一樣

gcc a.c -lwiringPi -lpthread

用到這個庫的時候,我們同樣需要鏈接_install/lib里面的libcurl.so動態(tài)庫 (.a是靜態(tài)庫)

頭文件主要是宏定義、聲明一些函數(shù)等,具體函數(shù)實(shí)現(xiàn)在動態(tài)庫里面。

調(diào)用libcurl編程訪問百度主頁

把_install里的內(nèi)容結(jié)合一下示例代碼來訪問一下百度。

代碼

#include <stdio.h> #include <curl/curl.h>typedef unsigned int bool;//數(shù)據(jù)類型別名用typedef 有分號 #define true 1 //宏定義(替換)用define 無冒號 #define false 0bool getUrl(char *filename)//GET請求 {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>指向的文件,//即為filename文件,而主函數(shù)傳入的參數(shù)是 /tmp/get.html,即為真正保存在get.html文件中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)//POST請求 {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 "); // 指定urlcurl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);res = curl_easy_perform(curl);//執(zhí)行curl_easy_cleanup(curl);}fclose(fp);return true; } int main(void) {getUrl("/tmp/get.html");postUrl("/tmp/post.html"); }

為什么要有最開始的那三句代碼呢?
類似于bool,true,faluse,這是C99標(biāo)準(zhǔn)才會支持,C++里有專門的bool類型,用來表示真或假。但是在C語言里沒有這樣的類型,為了修改方便直接這樣替換。

編譯注意(編譯時鏈接庫、頭文件路徑,運(yùn)行需添加動態(tài)庫為環(huán)境變量)

鏈接庫和頭文件再編譯,同時注意指明他們的路徑

gcc getAndPost.c -I ./curl-7.71.1/_install/include/ -L ./curl-7.71.1/_install/lib/ -lcurl

注意:動態(tài)庫靜態(tài)庫的鏈接用-L,而頭文件用-I

錯誤排查:

(1)提示找不到頭文件#include <curl/curl.h>,說明沒有指明頭文件的路徑

(2)如果只是使用-L是默認(rèn)去usr/lib下去找的,會提示找不到庫文件的路徑cannot find -lcurl

(3)如果編譯報錯一堆函數(shù)不認(rèn)識,函數(shù)是存在庫里面的,說明沒有鏈接庫

usr/bin/ld: getAndPost.c:(.text+0x1a2): undefined reference to `curl_easy_init' /usr/bin/ld: getAndPost.c:(.text+0x1d2): undefined reference to `curl_easy_setopt' /usr/bin/ld: getAndPost.c:(.text+0x1f6): undefined reference to `curl_easy_setopt' /usr/bin/ld: getAndPost.c:(.text+0x217): undefined reference to `curl_easy_setopt' /usr/bin/ld: getAndPost.c:(.text+0x238): undefined reference to `curl_easy_setopt' /usr/bin/ld: getAndPost.c:(.text+0x244): undefined reference to `curl_easy_perform'

可以看到已經(jīng)生成了可執(zhí)行文件./a.out

直接運(yùn)行這個./a.out是會報錯的(為什么我沒有報錯??可能是我用的Ubuntu20,老師是18.04??不,很有可能是因?yàn)槲耶?dāng)時網(wǎng)絡(luò)是斷開的)

error while loading shared libraries: libcurl.so.4:cannot open shared object file:no such file or directory

原因是運(yùn)行時要鏈接動態(tài)庫,沒有添加環(huán)境變量,忘記怎么添加咋辦?面向百度,export lib path

export LD_LIBRARY_PATH=./curl-7.71.1/_install/lib/

成功運(yùn)行后,可以看到vi /tmp/get.html中已經(jīng)有了百度官網(wǎng)的代碼。(僅貼出部分)


這跟我們平常去訪問百度是一樣的,只是用了前端css去排版的比較好看罷了,當(dāng)你右鍵查看頁面源碼就知道了。

而vi /tmp/port.html里面不會有東西,因?yàn)樵L問失敗了:新浪的用戶和密碼不匹配。

libcurl函數(shù)庫常用字段解讀

1.curl_global_init():初始化libcurl

函數(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.curl_easy_init():拿到句柄

用來初始化一個CURL的指針(有些像返回FILE類型的指針一樣)。相應(yīng)的在調(diào)用結(jié)束時要用curl_easy_cleanup函數(shù)清理。

一般curl_easy_init意味著一個會話的開始. 它會返回一個easy_handle(CURL*對象), 一般都用在easy系列的函數(shù)中。

后續(xù)所有的操作都是對這個指針進(jìn)行設(shè)置,把這種類型的指針就叫做句柄,實(shí)例:

其實(shí)socket服務(wù)器再socket函數(shù)后生成的fd,后續(xù)的bind,accept等操作也是基于這個fd,也可以理解為句柄

3.curl_easy_setopt(CURL *handle, CURLoption option, parameter):設(shè)置傳輸選項(xiàng)

參數(shù):1)CURL類型的指針 (2)CURLoption類型的選項(xiàng).(都在curl.h庫里有定義,man 也可以查看到)3)parameter 既可以是個函數(shù)的指針,也可以是某個對象的指針,也可以是個long型的變量,取決于第二個參數(shù)。

根據(jù)設(shè)置的傳輸選項(xiàng),實(shí)現(xiàn)回調(diào)函數(shù)以完成用戶特定任務(wù)(設(shè)置與操作句柄)

這個函數(shù)很重要,幾乎所有的curl 程序都要頻繁的使用它。它告訴curl庫,程序?qū)⒂腥绾蔚男袨?#xff0c;比如要查看一個網(wǎng)頁的html代碼等。(這個函數(shù)有些像ioctl函數(shù))

第二個參數(shù)CURLoption常用的宏:

  • (1)CURLOPT_URL: 設(shè)置訪問URL,就是設(shè)置訪問的網(wǎng)址
  • (2)CURLOPT_POSTFIELDS

post請求中:以&拼接字符串的形式把參數(shù)鏈接起來,下篇文章提到的翔云人工智能平臺OCRkey和密碼就要放在這里傳輸。

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86"); // 指定post內(nèi)容:用戶信息,嘗試登陸新浪郵箱
  • (3)CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA

CURLOPT_WRITEFUNCTION使用舉例:

回調(diào)函數(shù):網(wǎng)頁有數(shù)據(jù)請求回來的時候,如何去處理這些數(shù)據(jù)。(做人臉識別,肯定要獲得人臉識別的結(jié)果)

設(shè)置的回調(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ù)保存的功能,如處理下載文件。

①陳老師的車牌識別車牌識別

int BufferWriterFunc(char* data,size_t size,size_t nmemb,char *buffer) {strcpy(bufferData,data);//把返回的data數(shù)據(jù)放在本地的bufferData數(shù)組中return size*nmemb; }//配置如下: curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,BufferWriterFunc);

②修改上面訪問百度的代碼

size_t readData(void *ptr, size_t size, size_t nmemb, void *stream) {char buf[1024] = {'\0'};strncpy(buf,ptr,1024);printf("===========get data ===========\n");printf("%s\n",buf); }curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,readData);
CURLOPT_WRITEDATA使用舉例

也可以通過 CURLOPT_WRITEDATA屬性給默認(rèn)回調(diào)函數(shù)傳遞一個已經(jīng)打開的文件指針,用于將數(shù)據(jù)輸出到文件里。

正如上面訪問百度的例子:

FILE *fp; if ((fp = fopen(filename, "w")) == NULL)//提前打開了一個文件流return false;curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);//請求回來的所有數(shù)據(jù)都放到文件中

4.curl_easy_perform():執(zhí)行任務(wù)

在初始化CURL類型的指針 以及curl_easy_setopt完成后調(diào)用. 就像字面的意思所說perform就像是個舞臺.讓我們設(shè)置的option 運(yùn)作起來。

5.curl_easy_cleanup():釋放內(nèi)存

結(jié)束libcurl使用的時候,用來對curl_global_init做的工作清理。類似于close的函數(shù)。

該死的a庫不好用

./a.out: /usr/lib/arm-linux-gnueabihf/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by ./curl-7.71.1/_install/lib/libcurl.so.4)

往期文章

網(wǎng)絡(luò)編程知識預(yù)備(1) ——了解OSI網(wǎng)絡(luò)模型
網(wǎng)絡(luò)編程知識預(yù)備(2) ——淺顯易懂的三次握手與四次揮手
網(wǎng)絡(luò)編程知識預(yù)備(3) ——SOCKET、TCP、HTTP之間的區(qū)別與聯(lián)系
網(wǎng)絡(luò)編程知識預(yù)備(4) ——了解HTTP協(xié)議與HTTPS協(xié)議
網(wǎng)絡(luò)編程知識預(yù)備(5) ——libcurl庫簡介及其編程訪問百度首頁

總結(jié)

以上是生活随笔為你收集整理的网络编程知识预备(5) ——libcurl库简介及其编程访问百度首页的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。