首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

libcurl 入門教學:Easy 介面核心函式與 HTTP 下載實戰

     編輯:關於C語言

前言

libcurl 是功能強大的 URL 傳輸庫,支援 HTTP、HTTPS、FTP、FTPS、SFTP 等協定。本文聚焦 Easy 介面(同步、單執行緒),足以應對多數下載/上傳需求。

核心流程四步驟

CURL *curl = curl_easy_init();           // 1. 初始化
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.zip"); // 2. 設定選項
curl_easy_perform(curl);                 // 3. 執行傳輸
curl_easy_cleanup(curl);                 // 4. 清理資源

關鍵函式詳解

全域初始化/清理(程式啟動/結束各呼叫一次)

curl_global_init(CURL_GLOBAL_DEFAULT); // 載入 SSL、WinSock 等
// ... 使用 curl_easy_* ...
curl_global_cleanup();
  • CURL_GLOBAL_ALL:全部子系統(SSL、Win32、IDN 等)。
  • CURL_GLOBAL_SSL:僅 SSL/TLS。
  • CURL_GLOBAL_WIN32:僅 WinSock。
  • CURL_GLOBAL_NOTHING:不初始化(手動管理)。
  • 非執行緒安全,請在主執行緒單獨呼叫。

Easy Handle 生命週期

函式說明
curl_easy_init()建立 handle,回傳 CURL*;失敗回傳 NULL。內部會自動呼叫 curl_global_init(若未初始化),但建議手動控制。
curl_easy_cleanup(handle)釋放 handle 相關資源(連線、SSL session、DNS cache 等)。必須成對呼叫。
curl_easy_duphandle(handle)複製 handle(含所有選項),不複製狀態(連線、SSL、cookies)。新 handle 仍需 cleanup。
curl_easy_reset(handle)重置 handle 到初始狀態(保留連線、DNS、cookies、share)。

核心設定:curl_easy_setopt

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...);

所有行為透過 option + 參數控制。常用選項:

選項參數類型用途
CURLOPT_URLchar*目標 URL
CURLOPT_WRITEFUNCTIONcallback資料寫入回呼 size_t (*)(char*, size_t, size_t, void*)
CURLOPT_WRITEDATAvoid*傳給 WRITEFUNCTION 的 user pointer
CURLOPT_READFUNCTIONcallback上傳資料讀取回呼
CURLOPT_READDATAvoid*傳給 READFUNCTION 的 user pointer
CURLOPT_HEADERFUNCTIONcallbackHeader 處理回呼
CURLOPT_TIMEOUTlong整體逾時(秒)
CURLOPT_CONNECTTIMEOUTlong連線階段逾時(秒)
CURLOPT_FOLLOWLOCATIONlong自動追蹤 3xx 重導向 (1=開啟)
CURLOPT_SSL_VERIFYPEERlong驗證伺服器憑證 (0=跳過,測試用)
CURLOPT_USERAGENTchar*自定 User-Agent
CURLOPT_POSTlong啟用 POST (1=POST)
CURLOPT_POSTFIELDSchar*POST 資料內容
CURLOPT_HTTPHEADERstruct curl_slist*自定 HTTP Header 串列
CURLOPT_ERRORBUFFERchar*錯誤訊息緩衝區 (需 ≥ CURL_ERROR_SIZE)

執行與資訊取得

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
    fprintf(stderr, "curl error: %s\n", curl_easy_strerror(res));
}

// 取得傳輸資訊
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
double total_time;
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time);
curl_off_t download_size;
curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &download_size);

完整下載範例:儲存到檔案

#include <stdio.h>
#include <curl/curl.h>

size_t write_callback(void *ptr, size_t size, size_t nmemb, FILE *fp) {
    return fwrite(ptr, size, nmemb, fp);
}

int main() {
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL *curl = curl_easy_init();
    if (!curl) return 1;

    FILE *fp = fopen("download.zip", "wb");
    if (!fp) { curl_easy_cleanup(curl); return 1; }

    curl_easy_setopt(curl, CURLOPT_URL, "https://speed.hetzner.de/100MB.bin");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300L); // 5 分鐘逾時

    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) fprintf(stderr, "Download failed: %s\n", curl_easy_strerror(res));

    fclose(fp);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return 0;
}

進階功能速覽

  • URL 編碼/解碼:curl_easy_escape/curl_easy_unescape(記得 curl_free 釋放結果)。
  • 暫停/繼續:curl_easy_pause(handle, CURLPAUSE_RECV|CURLPAUSE_SEND)。
  • 原始 Socket 收發:curl_easy_recv/curl_easy_send(需 CURLOPT_CONNECT_ONLY)。
  • 多執行緒/並發:請改用 Multi 介面(curl_multi_*),支援非同步、單執行緒管理多連線。

常見坑與最佳實踐

  1. **永遠檢查回傳碼**:CURLE_OK 才成功;錯誤碼對應 curl_easy_strerror。
  2. **SSL 驗證**:生產環境務必保持 CURLOPT_SSL_VERIFYPEER=1、CURLOPT_SSL_VERIFYHOST=2。
  3. **回呼函式簽名**:嚴格遵循 size_t (*)(char*, size_t, size_t, void*),回傳實際處理位元組數;返回 0 非錯誤,表示「暫無資料」。
  4. **大檔案支援**:使用 curl_off_t 相關選項(CURLOPT_INFILESIZE_LARGE 等)。
  5. **清理順序**:先 curl_easy_cleanup,最後 curl_global_cleanup;切勿在 global cleanup 後仍使用 handle。

libcurl Easy 介面簡潔而強大,掌握核心流程與關鍵選項,即可快速實作健壯的 HTTP/HTTPS/FTP 客戶端。複雜場景(並發、非同步、WebSocket)請進階學習 Multi 介面與 libcurl 內部架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved