C++中LibCurl庫使用流程及配置詳解
LibCurl庫使用介紹
libcurl是一個(gè)跨平臺(tái)的開源網(wǎng)絡(luò)傳輸庫,它支持許多協(xié)議,包括HTTP、HTTPS、FTP、FTPS、SCP、SFTP、TFTP、LDAP、以及許多其他協(xié)議和文件傳輸方式。libcurl允許開發(fā)者使用C語言編寫代碼來進(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ù),使開發(fā)者能夠定制和控制網(wǎng)絡(luò)通信的細(xì)節(jié)。易用性: libcurl的API設(shè)計(jì)簡(jiǎn)單直觀,容易上手,同時(shí)也提供了豐富的文檔和示例。
libcurl的主要特點(diǎn)包括:
由于其強(qiáng)大的功能和易用性,libcurl被廣泛應(yīng)用于各種軟件和項(xiàng)目中,包括網(wǎng)絡(luò)爬蟲、下載工具、Web服務(wù)等。
libcurl使用基本流程
- 初始化CURL庫:
curl_global_init(CURL_GLOBAL_ALL);需要初始化libcurl庫,這可以通過調(diào)用curl_global_init()函數(shù)來完成。該函數(shù)在整個(gè)程序運(yùn)行期間只需要調(diào)用一次。多線程下最好主動(dòng)調(diào)用該函數(shù)以防止在線程中curl_easy_init時(shí)多次調(diào)用,不要在每個(gè)線程中都調(diào)用curl_global_init,應(yīng)該將該函數(shù)的調(diào)用放在主線程中。
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 類型的錯(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ù)寫入文件 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: 枚舉類型 CURLoption,表示要設(shè)置的選項(xiàng)類型。 // - parameter: 選項(xiàng)對(duì)應(yīng)的參數(shù)值,類型根據(jù)不同選項(xiàng)而定,既可以是個(gè)函數(shù)的指針,也可以是某個(gè)對(duì)象的指針,也可以是個(gè)long型的變量 常見CURLoption類型(更多CURLoption類型的選項(xiàng)都在curl.h庫里有定義,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è)置寫數(shù)據(jù)回調(diào)函數(shù)。 CURLOPT_WRITEDATA: 設(shè)置寫數(shù)據(jù)回調(diào)函數(shù)的用戶數(shù)據(jù)。 CURLOPT_PROXY: 設(shè)置代理服務(wù)器地址。 CURLOPT_SSL_VERIFYPEER: 設(shè)置是否驗(yàn)證對(duì)等證書。 CURLOPT_SSL_VERIFYHOST: 設(shè)置是否驗(yàn)證主機(jī)名。 CURLOPT_CUSTOMREQUEST: 設(shè)置自定義請(qǐng)求方法。 CURLOPT_USERAGENT: 設(shè)置用戶代理信息。 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è)置寫數(shù)據(jù)回調(diào)函數(shù) curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);//設(shè)置回調(diào)函數(shù)用戶數(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ì)等證書
部分枚舉類型選項(xiàng)對(duì)應(yīng)參數(shù)值說明
CURLOPT_WRITEFUNCTION 和 CURLOPT_WRITEDATA: 是配合使用的選項(xiàng),用于設(shè)置寫數(shù)據(jù)回調(diào)函數(shù)和回調(diào)函數(shù)的用戶數(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 的用戶數(shù)據(jù)指針。 //返回值:回調(diào)函數(shù)返回接收到的數(shù)據(jù)大小。
CURLOPT_WRITEDATA選項(xiàng)用于設(shè)置回調(diào)函數(shù)的用戶數(shù)據(jù)指針,該指針將被傳遞給回調(diào)函數(shù)作為其第四個(gè)參數(shù)。通常情況下,該指針指向一個(gè)結(jié)構(gòu)體或?qū)ο?,用于在回調(diào)函數(shù)中存儲(chǔ)處理過程中需要的狀態(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ù),用于在下載過程中更新下載進(jìn)度。注意:若無需使用額外的用戶數(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` 的用戶數(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è)置用戶數(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)景,例如下載文件、訪問網(wǎng)頁等。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é)處開始下載,直到 end 字節(jié)結(jié)束。如果 end 留空,則表示下載從 start 字節(jié)開始到文件末尾。用于指定下載文件的范圍,允許下載文件的任意部分內(nèi)容,不僅僅限于斷點(diǎn)續(xù)傳。- CURLOPT_RESUME_FROM:該選項(xiàng)用于設(shè)置斷點(diǎn)續(xù)傳的起始位置,即指定從文件的哪個(gè)字節(jié)處開始繼續(xù)下載。它的參數(shù)是一個(gè)長(zhǎng)整型值,表示斷點(diǎn)續(xù)傳的起始字節(jié)位置,主要用于實(shí)現(xiàn)斷點(diǎn)續(xù)傳,指定從文件的指定位置開始繼續(xù)下載
CURLOPT_VERBOSE是 libcurl 中的一個(gè)選項(xiàng),選項(xiàng)值類型:long,用于控制是否打印詳細(xì)的調(diào)試信息。設(shè)置為非零值時(shí),libcurl 將打印出大量的調(diào)試信息,包括請(qǐng)求和響應(yīng)的頭部、數(shù)據(jù)傳輸?shù)脑敿?xì)信息等。這些信息對(duì)于調(diào)試和排查問題非常有用,但在正常情況下可能會(huì)顯得冗長(zhǎng)。通常不會(huì)將CURLOPT_VERBOSE設(shè)置為非零值,因?yàn)榇蛴〈罅康恼{(diào)試信息會(huì)影響程序的性能并增加日志的大小。但在調(diào)試和開發(fā)階段,可以將其設(shè)置為非零值來幫助排查問題。
執(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ò)誤描述字符串,可以通過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): 無法解析主機(jī)名。
CURLE_COULDNT_CONNECT (7): 無法連接到主機(jī)或代理。
CURLE_OPERATION_TIMEDOUT (28): 操作超時(shí)。
CURLE_SSL_CONNECT_ERROR (35): SSL/TLS 連接錯(cuò)誤。
CURLE_PEER_FAILED_VERIFICATION (51): 對(duì)等證書驗(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): 證書問題。
CURLE_SSL_CIPHER (59): SSL/TLS 密碼錯(cuò)誤。
CURLE_SSL_CACERT (60): 未找到合適的 CA 證書。
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;
};
// 定義寫數(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ì)算本次寫入的數(shù)據(jù)總大小(size是單個(gè)數(shù)據(jù)塊大小,nmemb是塊的數(shù)量)
// 獲取傳遞進(jìn)來的DownloadData結(jié)構(gòu)體指針
struct DownloadData *downloadData = (struct DownloadData *) userp;
// 將數(shù)據(jù)塊寫入文件,返回實(shí)際寫入的大小
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庫
CURL *curl = curl_easy_init(); // 獲取一個(gè)CURL句柄用于本次傳輸
if (curl) {
const char *outputFileName = "aaa.txt";
struct DownloadData downloadData;
// 以二進(jìn)制寫模式打開輸出文件
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ù)寫入文件
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庫資源
return 0;
}
以上就是C++中LibCurl庫使用流程及配置詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ LibCurl庫使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
win10環(huán)境下C++ vs2015編譯opencv249的教程
這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Qt使用QtConcurrent::run實(shí)現(xiàn)異步等待和同步調(diào)用
Qt使用QtConcurrent::run實(shí)現(xiàn)C#中類似async await的用法,雖不如C#的async/await靈活,但可滿足業(yè)務(wù)需求并提升代碼可讀性,下面就來詳細(xì)的介紹一下QtConcurrent::run實(shí)現(xiàn)異步等待和同步調(diào)用2025-09-09
Cocos2d-x UI開發(fā)之CCControlSwitch控件類使用實(shí)例
這篇文章主要介紹了Cocos2d-x UI開發(fā)之CCControlSwitch控件類使用實(shí)例,本文代碼中含大量注釋講解了CCControlSwitch控件類的使用,需要的朋友可以參考下2014-09-09

