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

libcurl 實戰:C 語言構建高性能 HTTP 客戶端完整指南

     編輯:關於C語言

libcurl:C/C++ 網絡開發的瑞士軍刀

libcurl 是功能最全、移植性最好、性能最強的開源 URL 传輸庫,支持 HTTP/HTTPS/FTP/SMTP 等 20+ 協議。本文基於 libcurl Easy API,構建一個完整的 HTTP 客戶端,演示從初始化、配置、執行、回調處理到清理的全流程。

核心架構:Easy Interface

  • CURL *handle:會話句柄,維護單次傳輸狀態。
  • curl_easy_setopt():配置行為 (URL、回調、超時、頭部、代理、SSL 等)。
  • curl_easy_perform():阻塞執行傳輸,完成或出錯前不返回。
  • curl_easy_cleanup():釋放句柄資源。

關鍵回調函數:CURLOPT_WRITEFUNCTION

當 libcurl 接收到數據時,會多次調用此回調,將數據塊傳遞給應用層。應用層需負責緩衝區管理 (擴容、拷貝、終止符)。

完整 HTTP 客戶端實現

#include 
#include 
#include 
#include 

#define MAX_BUF 65536 // 64KB 初始緩衝區

// 動態緩衝區上下文
struct WriteContext {
    char *buffer;
    size_t size;      // 當前分配大小
    size_t len;       // 已用長度
    int error;        // 錯誤標誌
};

// 寫入回調:數據到達時調用
static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct WriteContext *ctx = (struct WriteContext*)userp;
    
    // 1. 擴容檢查 (指數增長策略)
    if (ctx->len + realsize >= ctx->size) {
        size_t new_size = ctx->size ? ctx->size * 2 : MAX_BUF;
        while (ctx->len + realsize >= new_size) new_size *= 2;
        char *new_buf = realloc(ctx->buffer, new_size);
        if (!new_buf) { ctx->error = 1; return 0; } // 返回 0 通知 curl 中止
        ctx->buffer = new_buf;
        ctx->size = new_size;
    }
    
    // 2. 拷貝數據
    memcpy(ctx->buffer + ctx->len, contents, realsize);
    ctx->len += realsize;
    ctx->buffer[ctx->len] = '\0'; // 字符串終止 (便於直接 printf)
    
    return realsize; // 返回處理字節數,告知 curl 成功
}

int main(void) {
    CURL *curl;
    CURLcode res;
    struct WriteContext ctx = {0};
    
    // 1. 初始化
    curl = curl_easy_init();
    if (!curl) { fprintf(stderr, "curl_easy_init 失敗\n"); return 1; }
    
    // 2. 配置 URL
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com");
    
    // 3. 配置寫入回調與上下文
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ctx);
    
    // 4. 推薦配置 (生產環境必備)
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);        // 總超時 10秒
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);  // 連接超時 5秒
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);  // 自動跟隨重定向
    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);       // 最大重定向次數
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    // CURLOPT_SSL_VERIFYPEER 0 僅用於測試,生產必須驗證證書
    
    // 5. 執行傳輸
    res = curl_easy_perform(curl);
    
    // 6. 結果處理
    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform 失敗: %s\n", curl_easy_strerror(res));
    } else if (ctx.error) {
        fprintf(stderr, "內存分配失敗\n");
    } else {
        long http_code = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        printf("HTTP 狀態碼: %ld\n", http_code);
        printf("響應長度: %zu\n", ctx.len);
        printf("響應內容:\n%s\n", ctx.buffer);
    }
    
    // 7. 清理
    free(ctx.buffer);
    curl_easy_cleanup(curl);
    return 0;
}

編譯鏈接命令

# Linux/macOS
gcc http_client.c -o http_client -lcurl

# Windows (MinGW)
gcc http_client.c -o http_client.exe -lcurl

# MSVC
cl http_client.c libcurl.lib

進階功能配置速查表

需求CURLOPT 選項示例值
POST 數據CURLOPT_POST, CURLOPT_POSTFIELDS1, "key=value&a=b"
自定義請求頭CURLOPT_HTTPHEADERstruct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/json");
HTTPS 驗證CURLOPT_CAINFO, CURLOPT_SSL_VERIFYPEER"cacert.pem", 1L
代理設置CURLOPT_PROXY, CURLOPT_PROXYTYPE"https://proxy:8080", CURLPROXY_HTTP
斷點續傳CURLOPT_RESUME_FROM_LARGE(curl_off_t)offset
多文件上傳CURLOPT_MIMEPOST (curl_mime_* API)構建 mime 結構
獲取響應頭CURLOPT_HEADERFUNCTION, CURLOPT_HEADERDATA類似 write_callback
Cookie 管理CURLOPT_COOKIEJAR, CURLOPT_COOKIEFILE"cookies.txt"

高併發場景:Multi Interface

Easy API 是同步阻塞的。高併發 (數百上千連接) 需使用 Multi Interface:

CURLM *multi = curl_multi_init();
// 添加多個 easy handle: curl_multi_add_handle(multi, easy_handle);
// 事件循環: curl_multi_perform() + curl_multi_poll() / select()
// 移除完成: curl_multi_remove_handle()
curl_multi_cleanup(multi);

總結

libcurl Easy API 以「句柄 + 選項 + 回調」的靈活設計,將複雜的協議細節封裝為簡潔的 C 接口。掌握 WRITEFUNCTION 動態緩衝區管理、超時與重定向控制、SSL 驗證、Multi Interface 異步模型,即可構建生產級 HTTP 客戶端。建議閱讀 curl.h 並實戰封裝一個適合項目風格的 C++ Wrapper (RAII 管理資源、異常處理、鏈式調用)。

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