首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言使用 libcurl 實現 HTTP POST 請求與日誌記錄完整示例

     編輯:程式設計綜合問答

依賴準備

  • 安裝 libcurl 開發包:`apt-get install libcurl4-openssl-dev` (Ubuntu) / `vcpkg install curl` (Windows)。
  • 鏈接庫:`-lcurl` (GCC/Clang) 或 `libcurl.lib` (MSVC)。
  • 頭文件:`#include `。

核心邏輯封裝

封裝一個通用的 `http_post` 函數,支持自定義 URL、表單數據、寫入回調、錯誤處理、Cookie 持久化。

完整可編譯代碼

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

// 回調函數:將響應數據寫入 FILE*
static size_t write_callback(void* buffer, size_t size, size_t nmemb, void* userp) {
    FILE* fp = (FILE*)userp;
    return fwrite(buffer, size, nmemb, fp);
}

// 通用 POST 函數
// 返回 0 成功,非 0 失敗 (錯誤碼見 CURLE_*)
int http_post(const char* url, const char* post_fields, const char* response_file, const char* cookie_file) {
    CURL* curl = curl_easy_init();
    if (!curl) { fprintf(stderr, "curl_easy_init failed\n"); return -1; }

    FILE* fp = fopen(response_file, "wb");
    if (!fp) { fprintf(stderr, "fopen %s failed\n", response_file); curl_easy_cleanup(curl); return -2; }

    // 設置選項
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // 支持 3xx 重定向
    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_file); // 讀取 Cookie
    curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_file);  // 保存 Cookie (登錄態保持)
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);           // 調試輸出
    curl_easy_setopt(curl, CURLOPT_HEADER, 1L);            // 將響應頭也寫入文件
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);          // 超時 30s
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);   // 連接超時 10s
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);    // 忽略證書驗證 (測試用,生產應配置 CA)
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    // 執行請求
    CURLcode res = curl_easy_perform(curl);
    long http_code = 0;
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);

    fclose(fp);
    curl_easy_cleanup(curl);

    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform failed: %s\n", curl_easy_strerror(res));
        return res;
    }
    if (http_code != 200) {
        fprintf(stderr, "HTTP error: %ld\n", http_code);
        return -3;
    }
    return 0;
}

// 日誌文件追記讀取並逐行 POST (模擬需求偽代碼)
void process_log_queue(const char* url, const char* log_file) {
    FILE* fp = fopen(log_file, "r+");
    if (!fp) return;
    char line[4096];
    long pos = 0;
    while (fgets(line, sizeof(line), fp)) {
        // 去除換行
        line[strcspn(line, "\r\n")] = 0;
        if (strlen(line) == 0) continue;

        char response_file[256];
        sprintf(response_file, "resp_%ld.tmp", time(NULL));
        int ret = http_post(url, line, response_file, "cookies.txt");
        if (ret == 0) {
            // 成功:從日誌文件中刪除該行 (簡易實現:重寫文件,實際建議用 SQLite 或單獨隊列文件)
            printf("POST success: %s\n", line);
        } else {
            printf("POST failed, keep in log: %s\n", line);
        }
    }
    fclose(fp);
}

int main() {
    curl_global_init(CURL_GLOBAL_ALL);

    // 示例 1: 直接 POST 登錄
    const char* login_url = "https://www.example.com/login";
    const char* login_data = "username=test&password=123456&remember=1";
    http_post(login_url, login_data, "login_resp.html", "cookies.txt");

    // 示例 2: 處理日誌隊列
    // process_log_queue("https://api.example.com/log", "log.txt");

    curl_global_cleanup();
    return 0;
}

關鍵點解析

  • 錯誤處理:檢查 `curl_easy_perform` 返回碼,獲取 `CURLINFO_RESPONSE_CODE` 判斷 HTTP 狀態。
  • Cookie 持久化:`CURLOPT_COOKIEFILE` (讀) + `CURLOPT_COOKIEJAR` (寫) 實現會話保持,模擬瀏覽器登錄態。
  • SSL/TLS:測試階段可關閉驗證 (`CURLOPT_SSL_VERIFYPEER=0`),生產必須配置 CA 證書路徑 (`CURLOPT_CAINFO`)。
  • 內存管理:`curl_global_init/cleanup` 進程級調用一次;`curl_easy_init/cleanup` 每請求一次。
  • 日誌隊列:偽代碼中「讀取->POST->成功刪除」邏輯在文件操作上有競態風險,生產環境建議使用 SQLite (WAL 模式) 或 Redis List 作為持久化隊列。

編譯命令

gcc -o curl_post curl_post.c -lcurl
# 或 MSVC
cl curl_post.c libcurl.lib
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved