C++中LibCurl庫(kù)使用流程及配置詳解
LibCurl庫(kù)使用介紹
libcurl是一個(gè)跨平臺(tái)的開(kāi)源網(wǎng)絡(luò)傳輸庫(kù),它支持許多協(xié)議,包括HTTP、HTTPS、FTP、FTPS、SCP、SFTP、TFTP、LDAP、以及許多其他協(xié)議和文件傳輸方式。libcurl允許開(kāi)發(fā)者使用C語(yǔ)言編寫(xiě)代碼來(lái)進(jìn)行網(wǎng)絡(luò)通信,并提供了簡(jiǎn)單易用的API接口。
跨平臺(tái)性: 可以在各種操作系統(tǒng)上使用,包括Linux、Windows、macOS等。多協(xié)議支持: 支持多種常用的網(wǎng)絡(luò)協(xié)議,例如HTTP、FTP等,以及安全協(xié)議如HTTPS、FTPS等。功能豐富: 提供了豐富的功能和選項(xiàng),可以用于各種網(wǎng)絡(luò)傳輸需求,如文件上傳、下載、POST請(qǐng)求等。高度可定制性: 提供了大量的選項(xiàng)和回調(diào)函數(shù),使開(kāi)發(fā)者能夠定制和控制網(wǎng)絡(luò)通信的細(xì)節(jié)。易用性: libcurl的API設(shè)計(jì)簡(jiǎn)單直觀(guān),容易上手,同時(shí)也提供了豐富的文檔和示例。
libcurl的主要特點(diǎn)包括:
由于其強(qiáng)大的功能和易用性,libcurl被廣泛應(yīng)用于各種軟件和項(xiàng)目中,包括網(wǎng)絡(luò)爬蟲(chóng)、下載工具、Web服務(wù)等。
libcurl使用基本流程
- 初始化CURL庫(kù):
curl_global_init(CURL_GLOBAL_ALL);
需要初始化libcurl庫(kù),這可以通過(guò)調(diào)用curl_global_init()函數(shù)來(lái)完成。該函數(shù)在整個(gè)程序運(yùn)行期間只需要調(diào)用一次。多線(xiàn)程下最好主動(dòng)調(diào)用該函數(shù)以防止在線(xiàn)程中curl_easy_init時(shí)多次調(diào)用,不要在每個(gè)線(xiàn)程中都調(diào)用curl_global_init,應(yīng)該將該函數(shù)的調(diào)用放在主線(xiàn)程中。
CURLcode curl_global_init(long flags); //這個(gè)函數(shù)只能用一次。(調(diào)用curl_global_cleanup清理后可再次使用初始化) //參數(shù):flags //CURL_GLOBAL_ALL: 初始化所有的 libcurl 功能。 //CURL_GLOBAL_SSL: 初始化 SSL 相關(guān)的功能,如支持 HTTPS 議。 //CURL_GLOBAL_WIN32: 在 Windows 平臺(tái)上初始化一些特定的功能。 //CURL_GLOBAL_NOTHING: 不做任何初始化,這種情況下需要手動(dòng)初始化特定的功能。 //返回值: CURLcode 類(lèi)型的錯(cuò)誤碼,如果初始化成功則返回 CURLE_OK,否則返回其他錯(cuò)誤碼表示初始化失敗
- 獲取一個(gè)CURL句柄用于本次傳輸:
CURL *curl = curl_easy_init();
成功,則返回指向新創(chuàng)建的 CURL 句柄的指針;如果出現(xiàn)錯(cuò)誤,則返回 NULL。 - 設(shè)置的傳輸配置選項(xiàng): 使用curl_easy_setopt() 函數(shù)設(shè)置HTTP請(qǐng)求的選項(xiàng),如URL、請(qǐng)求頭、請(qǐng)求體等等。如:
curl_easy_setopt(curl, CURLOPT_URL, url.data()); // 設(shè)置要下載的URL地址 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // 設(shè)置回調(diào)函數(shù)以將數(shù)據(jù)寫(xiě)入文件 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadData); // 傳遞包含輸出文件指針、進(jìn)度等的結(jié)構(gòu)體給回調(diào)函數(shù)
curl_easy_setopt() 函數(shù)詳解:
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter); //參數(shù): // - handle: 指向 CURL 句柄的指針,表示要設(shè)置選項(xiàng)的 CURL 句柄。 // - option: 枚舉類(lèi)型 CURLoption,表示要設(shè)置的選項(xiàng)類(lèi)型。 // - parameter: 選項(xiàng)對(duì)應(yīng)的參數(shù)值,類(lèi)型根據(jù)不同選項(xiàng)而定,既可以是個(gè)函數(shù)的指針,也可以是某個(gè)對(duì)象的指針,也可以是個(gè)long型的變量 常見(jiàn)CURLoption類(lèi)型(更多CURLoption類(lèi)型的選項(xiàng)都在curl.h庫(kù)里有定義,man 也可以查看到): CURLOPT_URL: 設(shè)置請(qǐng)求的 URL。 CURLOPT_HTTPHEADER: 設(shè)置請(qǐng)求頭信息。 CURLOPT_POSTFIELDS: 設(shè)置請(qǐng)求體數(shù)據(jù)。 CURLOPT_TIMEOUT: 設(shè)置請(qǐng)求超時(shí)時(shí)間。 CURLOPT_WRITEFUNCTION: 設(shè)置寫(xiě)數(shù)據(jù)回調(diào)函數(shù)。 CURLOPT_WRITEDATA: 設(shè)置寫(xiě)數(shù)據(jù)回調(diào)函數(shù)的用戶(hù)數(shù)據(jù)。 CURLOPT_PROXY: 設(shè)置代理服務(wù)器地址。 CURLOPT_SSL_VERIFYPEER: 設(shè)置是否驗(yàn)證對(duì)等證書(shū)。 CURLOPT_SSL_VERIFYHOST: 設(shè)置是否驗(yàn)證主機(jī)名。 CURLOPT_CUSTOMREQUEST: 設(shè)置自定義請(qǐng)求方法。 CURLOPT_USERAGENT: 設(shè)置用戶(hù)代理信息。 CURLOPT_VERBOSE: 設(shè)置是否輸出詳細(xì)的調(diào)試信息。 CURLOPT_FOLLOWLOCATION: 設(shè)置是否跟隨重定向。 CURLOPT_COOKIE: 設(shè)置請(qǐng)求中的 Cookie。 CURLOPT_COOKIEFILE: 設(shè)置從文件中讀取 Cookie。 CURLOPT_COOKIEJAR: 設(shè)置保存 Cookie 到文件。 CURLOPT_RESUME_FROM: 設(shè)置斷點(diǎn)續(xù)傳的起始位置。 CURLOPT_LOW_SPEED_LIMIT: 設(shè)置低速下載速度限制。 CURLOPT_LOW_SPEED_TIME: 設(shè)置低速下載持續(xù)時(shí)間。 CURLOPT_CONNECTTIMEOUT: 設(shè)置連接超時(shí)時(shí)間 例如: struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); //設(shè)置請(qǐng)求頭 curl_easy_setopt(curl, CURLOPT_URL, "http://example.com"); //設(shè)置 URL curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "key1=value1&key2=value2"); //設(shè)置請(qǐng)求體 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 設(shè)置請(qǐng)求超時(shí)時(shí)間,超時(shí)時(shí)間為10秒 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);//設(shè)置寫(xiě)數(shù)據(jù)回調(diào)函數(shù) curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);//設(shè)置回調(diào)函數(shù)用戶(hù)數(shù)據(jù) curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:8080"); //設(shè)置代理 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //設(shè)置 SSL 選項(xiàng), 禁止驗(yàn)證對(duì)等證書(shū)
部分枚舉類(lèi)型選項(xiàng)對(duì)應(yīng)參數(shù)值說(shuō)明
CURLOPT_WRITEFUNCTION
和 CURLOPT_WRITEDATA
: 是配合使用的選項(xiàng),用于設(shè)置寫(xiě)數(shù)據(jù)回調(diào)函數(shù)和回調(diào)函數(shù)的用戶(hù)數(shù)據(jù)。
CURLOPT_WRITEFUNCTION
選項(xiàng)用于設(shè)置一個(gè)回調(diào)函數(shù),該函數(shù)在 libcurl 接收到 HTTP 響應(yīng)數(shù)據(jù)時(shí)被調(diào)用,用于處理接收到的數(shù)據(jù)?;卣{(diào)函數(shù)的原型如下(size_t function( void *ptr, size_t size,size_t nmemb, void *stream);
):
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata); //參數(shù): - ptr 是接收到的數(shù)據(jù)緩沖區(qū)指針, - size 是單個(gè)數(shù)據(jù)塊的大小, - nmemb 是數(shù)據(jù)塊的數(shù)量, - userdata 是傳遞給 CURLOPT_WRITEDATA 的用戶(hù)數(shù)據(jù)指針。 //返回值:回調(diào)函數(shù)返回接收到的數(shù)據(jù)大小。
CURLOPT_WRITEDATA
選項(xiàng)用于設(shè)置回調(diào)函數(shù)的用戶(hù)數(shù)據(jù)指針,該指針將被傳遞給回調(diào)函數(shù)作為其第四個(gè)參數(shù)。通常情況下,該指針指向一個(gè)結(jié)構(gòu)體或?qū)ο?,用于在回調(diào)函數(shù)中存儲(chǔ)處理過(guò)程中需要的狀態(tài)信息。
CURLOPT_HEADERFUNCTION
和CURLOPT_HEADERDATA
是 libcurl 中用于處理 HTTP 響應(yīng)頭的選項(xiàng),回調(diào)函數(shù):size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata);
,具體用法同上。CURLOPT_READFUNCTION
和CURLOPT_READDATA
是 libcurl 中用于處理請(qǐng)求體數(shù)據(jù)的選項(xiàng)?;卣{(diào)函數(shù):size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);
用法同上。CURLOPT_NOPROGRESS
,CURLOPT_PROGRESSFUNCTION
,CURLOPT_PROGRESSDATA
用于處理下載進(jìn)度的選項(xiàng)CURLOPT_NOPROGRESS
:該選項(xiàng)用于禁止或啟用 libcurl 的內(nèi)置下載進(jìn)度條功能。設(shè)置為 1 表示禁止內(nèi)置進(jìn)度條, 0 表示啟用內(nèi)置進(jìn)度條,默認(rèn)0;CURLOPT_PROGRESSFUNCTION
:設(shè)置一個(gè)回調(diào)函數(shù),用于在下載過(guò)程中更新下載進(jìn)度。注意:若無(wú)需使用額外的用戶(hù)數(shù)據(jù),將 nullptr 作為CURLOPT_PROGRESSDATA
的參數(shù)傳遞給 libcurl;回調(diào)函數(shù)的原型如下:
int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); //參數(shù): - clientp 是傳遞給 `CURLOPT_PROGRESSDATA` 的用戶(hù)數(shù)據(jù)指針, - dltotal 是預(yù)期下載總字節(jié)數(shù), - dlnow 是當(dāng)前已下載字節(jié)數(shù), - ultotal 是預(yù)期上傳總字節(jié)數(shù), - ulnow 是當(dāng)前已上傳字節(jié)數(shù)。 //返回值:回調(diào)函數(shù)應(yīng)該返回 0 以繼續(xù)下載操作,返回非零值表示終止下載操作。
CURLOPT_PROGRESSDATA
:設(shè)置用戶(hù)數(shù)據(jù)指針
CURLOPT_TIMEOUT
,`CURLOPT_CONNECTIONTIMEOUT,用于設(shè)置超時(shí)時(shí)間CURLOPT_TIMEOUT
:設(shè)置請(qǐng)求的總超時(shí)時(shí)間,即從發(fā)送請(qǐng)求到接收完整響應(yīng)的總時(shí)間。如果在指定的時(shí)間內(nèi)未完成請(qǐng)求,libcurl 將會(huì)放棄請(qǐng)求,并返回超時(shí)錯(cuò)誤。該選項(xiàng)的參數(shù)是一個(gè)長(zhǎng)整型值,表示超時(shí)時(shí)間的秒數(shù);用于對(duì)完整響應(yīng)時(shí)間比較關(guān)注的場(chǎng)景,例如下載文件、訪(fǎng)問(wèn)網(wǎng)頁(yè)等。CURLOPT_CONNECTTIMEOUT
:該選項(xiàng)用于設(shè)置連接超時(shí)時(shí)間,即建立連接的時(shí)間。如果在指定的時(shí)間內(nèi)未能建立連接,libcurl 將會(huì)放棄連接嘗試,并返回連接超時(shí)錯(cuò)誤。該選項(xiàng)的參數(shù)也是一個(gè)長(zhǎng)整型值,表示超時(shí)時(shí)間的秒數(shù);適用于對(duì)連接建立時(shí)間比較關(guān)注的場(chǎng)景,例如需要快速響應(yīng)的短連接請(qǐng)求
CURLOPT_RANGE
和CURLOPT_RESUME_FROM
是 libcurl 中用于實(shí)現(xiàn)斷點(diǎn)續(xù)傳CURLOPT_RANGE
:設(shè)置 HTTP 請(qǐng)求的范圍,即指定需要下載的文件的范圍。它的參數(shù)是一個(gè)字符串,格式為 start-end,表示從文件的 start 字節(jié)處開(kāi)始下載,直到 end 字節(jié)結(jié)束。如果 end 留空,則表示下載從 start 字節(jié)開(kāi)始到文件末尾。用于指定下載文件的范圍,允許下載文件的任意部分內(nèi)容,不僅僅限于斷點(diǎn)續(xù)傳。- CURLOPT_RESUME_FROM:該選項(xiàng)用于設(shè)置斷點(diǎn)續(xù)傳的起始位置,即指定從文件的哪個(gè)字節(jié)處開(kāi)始繼續(xù)下載。它的參數(shù)是一個(gè)長(zhǎng)整型值,表示斷點(diǎn)續(xù)傳的起始字節(jié)位置,主要用于實(shí)現(xiàn)斷點(diǎn)續(xù)傳,指定從文件的指定位置開(kāi)始繼續(xù)下載
CURLOPT_VERBOSE
是 libcurl 中的一個(gè)選項(xiàng),選項(xiàng)值類(lèi)型:long,用于控制是否打印詳細(xì)的調(diào)試信息。設(shè)置為非零值時(shí),libcurl 將打印出大量的調(diào)試信息,包括請(qǐng)求和響應(yīng)的頭部、數(shù)據(jù)傳輸?shù)脑敿?xì)信息等。這些信息對(duì)于調(diào)試和排查問(wèn)題非常有用,但在正常情況下可能會(huì)顯得冗長(zhǎng)。通常不會(huì)將CURLOPT_VERBOSE
設(shè)置為非零值,因?yàn)榇蛴〈罅康恼{(diào)試信息會(huì)影響程序的性能并增加日志的大小。但在調(diào)試和開(kāi)發(fā)階段,可以將其設(shè)置為非零值來(lái)幫助排查問(wèn)題。
執(zhí)行請(qǐng)求:
CURLcode res = curl_easy_perform(curl); //執(zhí)行HTTP請(qǐng)求
處理響應(yīng): 根據(jù)請(qǐng)求的結(jié)果進(jìn)行相應(yīng)的處理,如處理響應(yīng)數(shù)據(jù)、錯(cuò)誤處理等。
if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { // 請(qǐng)求成功,處理響應(yīng)數(shù)據(jù) } //以下是一些常用的 CURLcode 枚舉值,詳細(xì)的錯(cuò)誤描述字符串,可以通過(guò)const char *curl_easy_strerror(CURLcode errornum ) 這個(gè)函數(shù)取得 CURLE_OK (0): 操作成功完成。 CURLE_UNSUPPORTED_PROTOCOL (1): 不支持的協(xié)議。 CURLE_URL_MALFORMAT (3): URL 格式錯(cuò)誤。 CURLE_COULDNT_RESOLVE_HOST (6): 無(wú)法解析主機(jī)名。 CURLE_COULDNT_CONNECT (7): 無(wú)法連接到主機(jī)或代理。 CURLE_OPERATION_TIMEDOUT (28): 操作超時(shí)。 CURLE_SSL_CONNECT_ERROR (35): SSL/TLS 連接錯(cuò)誤。 CURLE_PEER_FAILED_VERIFICATION (51): 對(duì)等證書(shū)驗(yàn)證失敗。 CURLE_GOT_NOTHING (52): 未收到任何數(shù)據(jù)。 CURLE_SEND_ERROR (55): 發(fā)送數(shù)據(jù)時(shí)出錯(cuò)。 CURLE_RECV_ERROR (56): 接收數(shù)據(jù)時(shí)出錯(cuò)。 CURLE_SSL_CERTPROBLEM (58): 證書(shū)問(wèn)題。 CURLE_SSL_CIPHER (59): SSL/TLS 密碼錯(cuò)誤。 CURLE_SSL_CACERT (60): 未找到合適的 CA 證書(shū)。 CURLE_USE_SSL_FAILED (64): 使用 SSL/TLS 失敗。
- 清理: 執(zhí)行完HTTP請(qǐng)求后,需要清理資源,包括清理CURL句柄和釋放libcurl相關(guān)的資源。
curl_easy_cleanup(curl);
- 全局清理: 在程序結(jié)束前,需要對(duì)libcurl進(jìn)行全局清理,釋放相關(guān)資源。
curl_global_cleanup();
代碼示例:
#include <stdio.h> #include <curl/curl.h> struct DownloadData { FILE *file = nullptr; // 聲明為 null ; s32 fileSize; s32 downloaded; std::string hash; bool isInitialized = false; }; // 定義寫(xiě)數(shù)據(jù)回調(diào)函數(shù) size_t HttpDownloadService::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { // size_t data_size = size * nmemb; // 計(jì)算本次寫(xiě)入的數(shù)據(jù)總大小(size是單個(gè)數(shù)據(jù)塊大小,nmemb是塊的數(shù)量) // 獲取傳遞進(jìn)來(lái)的DownloadData結(jié)構(gòu)體指針 struct DownloadData *downloadData = (struct DownloadData *) userp; // 將數(shù)據(jù)塊寫(xiě)入文件,返回實(shí)際寫(xiě)入的大小 size_t write_size = fwrite(contents, size, nmemb, downloadData->file); downloadData->downloaded += write_size; // 更新已下載的總字節(jié)數(shù) if (downloadData->fileSize > 0) { downloaded = downloadData->downloaded; double progress = (double) downloadData->downloaded / downloadData->fileSize * 100; std::cout << " Download fileSize: " << downloadData->fileSize << " Download Progress: " << progress << "%" << std::endl; } return write_size; } int main() { curl_global_init(CURL_GLOBAL_ALL);// 初始化CURL庫(kù) CURL *curl = curl_easy_init(); // 獲取一個(gè)CURL句柄用于本次傳輸 if (curl) { const char *outputFileName = "aaa.txt"; struct DownloadData downloadData; // 以二進(jìn)制寫(xiě)模式打開(kāi)輸出文件 downloadData.file = fopen(outputFileName, "wb"); // Open the file and get FILE* pointer downloadData.fileSize = 7022; // 預(yù)期的總文件大小,字節(jié)數(shù) downloadData.downloaded = 0; // 已下載的字節(jié)數(shù) downloadData.hash = "8b32dbbdfcffc01ae7ff4cd29c9e4bfa973e9df29a629c80605d374d4237e2ba"; // 預(yù)期的下載文件SHA256哈希值 curl_easy_setopt(curl, CURLOPT_URL, “http://example.com”); // 設(shè)置要下載的URL地址 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // 設(shè)置回調(diào)函數(shù)以將數(shù)據(jù)寫(xiě)入文件 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadData); // 傳遞包含輸出文件指針、進(jìn)度等的結(jié)構(gòu)體給回調(diào)函數(shù) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); // 啟用進(jìn)度回調(diào) curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, nullptr); // 進(jìn)度回調(diào)函數(shù)可選,這里不使用 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); CURLcode res = curl_easy_perform(curl); // 執(zhí)行請(qǐng)求 if (res != CURLE_OK) { // 請(qǐng)求失敗,處理錯(cuò)誤 std::cout << "Download failed: {}: " << curl_easy_strerror(res)<< std::endl; } else { // 請(qǐng)求成功,處理響應(yīng)數(shù)據(jù) logger->Info(SRC_LOC, "Download completed successfully."); std::cout << "Download completed successfully. " << std::endl; //……eg:對(duì)比文件大小和hash檢查下載文件是否正常 } curl_easy_cleanup(curl); // 清理CURL句柄資源 fclose(downloadData.file); // Close the file } curl_global_cleanup(); // 清理CURL庫(kù)資源 return 0; }
以上就是C++中LibCurl庫(kù)使用流程及配置詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ LibCurl庫(kù)使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++基礎(chǔ)入門(mén)教程(三):數(shù)組、字符串、結(jié)構(gòu)體、共用體
這篇文章主要介紹了C++基礎(chǔ)入門(mén)教程(三):數(shù)組、字符串、結(jié)構(gòu)體、共用體,需要的朋友可以參考下2014-11-11用C/C++實(shí)現(xiàn)linux下檢測(cè)網(wǎng)絡(luò)接口狀態(tài)
這篇文章主要為大家詳細(xì)介紹了用c/c++實(shí)現(xiàn)linux下檢測(cè)網(wǎng)絡(luò)接口狀態(tài),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06C語(yǔ)言實(shí)現(xiàn)Fibonacci數(shù)列遞歸
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)Fibonacci數(shù)列遞歸,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02C++文件相關(guān)函數(shù)CreateFile|ReadFile|WriteFile用法詳解
這篇文章主要為大家詳細(xì)介紹了c++有關(guān)文件創(chuàng)建、讀取和寫(xiě)入的api:CreateFile、ReadFile、WriteFile的具體使用,需要的可以參考下2023-04-04