C语言HttpWebRequest如何发送GET请求?

99ANYc3cd6
预计阅读时长 25 分钟
位置: 首页 C语言 正文

C 语言标准库本身不包含任何用于网络请求(如 HTTP)的函数HttpWebRequest 是 C# (一个高级语言) 中 .NET 框架提供的一个非常方便的类。

c语言HttpWebRequest
(图片来源网络,侵删)

在 C 语言中,我们需要使用操作系统提供的底层网络 API,或者使用第三方库来简化这个过程,对于 Linux/Unix-like 系统,最标准、最常用的库是 libcurl,对于 Windows,你可以使用 WinINet 或 WinHTTP,但跨平台和功能最强大的选择仍然是 libcurl

这篇教程将主要围绕 libcurl 展开,因为它是在 C 语言中进行 HTTP 请求的事实标准。


什么是 libcurl?

libcurl 是一个免费、开源、客户端的 URL 传输库,它支持多种协议(HTTP, HTTPS, FTP, SMTP 等),它功能强大,稳定,并且被无数应用程序使用,你可以把它看作是 C 语言世界的“瑞士军刀”,专门用来处理各种网络连接和数据传输。


环境准备:安装 libcurl

在使用 libcurl 之前,你需要确保你的开发环境中已经安装了它和它的开发头文件。

c语言HttpWebRequest
(图片来源网络,侵删)

在 Linux (Debian/Ubuntu) 上:

sudo apt-get update
sudo apt-get install libcurl4-openssl-dev

在 Linux (Fedora/CentOS) 上:

sudo dnf install libcurl-devel

在 Windows 上:

  1. 下载: 从 libcurl 官网 下载预编译的二进制包(curl-8.x.x-win64-mingw.zip)。
  2. 配置:
    • include 文件夹中的头文件(如 curl.h)添加到你的编译器的 include 路径。
    • lib 文件夹中的库文件(如 libcurl.lib)添加到你的链接器设置中。
    • bin 文件夹中的 curl.dll 复制到你的可执行文件所在的目录,或者添加到系统的 PATH 环境变量中。

libcurl 的基本使用流程

使用 libcurl 的基本步骤非常清晰,类似于 C# 中 HttpWebRequest 的模式:

  1. 初始化: 调用 curl_easy_init() 创建一个 easy handle(句柄),这个句柄会保存所有关于此次请求的配置信息。
  2. 设置选项: 使用 curl_easy_setopt() 函数来配置你的请求,这是最核心的一步,你可以设置 URL、请求方法(GET/POST)、请求头、回调函数等。
  3. 执行: 调用 curl_easy_perform() 来执行请求,这个函数是阻塞的,直到请求完成或失败。
  4. 清理: 调用 curl_easy_cleanup() 来释放 easy handle 及其相关的所有资源。

核心代码示例

下面我们通过几个例子来展示如何使用 libcurl。

示例 1:发送一个简单的 GET 请求

这个例子会向 httpbin.org/get 发送一个 GET 请求,并将响应内容打印到标准输出。

#include <stdio.h>
#include <curl/curl.h>
// 这是一个回调函数,libcurl 会将接收到的数据块传递给这个函数
// size_t 是数据块的大小,nmemb 是数据块的数量
// 返回值必须是实际处理的数据大小
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    (void)userp; // 避免未使用参数的警告
    // 计算总字节数
    size_t realsize = size * nmemb;
    // 将数据直接写入标准输出
    fwrite(contents, 1, realsize, stdout);
    return realsize;
}
int main(void) {
    CURL *curl;
    CURLcode res;
    // 1. 初始化 libcurl
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (curl) {
        // 2. 设置 URL
        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get");
        // 设置一个回调函数,用于处理服务器返回的数据
        // CURLOPT_WRITEFUNCTION 指定你的回调函数
        // CURLOPT_WRITEDATA 指定传递给回调函数的额外参数(这里我们不需要,传NULL)
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
        // 3. 执行请求
        printf("Sending GET request to https://httpbin.org/get\n");
        res = curl_easy_perform(curl);
        // 检查执行结果
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }
        // 4. 清理
        curl_easy_cleanup(curl);
    }
    // 全局清理
    curl_global_cleanup();
    return 0;
}

编译和运行 (Linux):

c语言HttpWebRequest
(图片来源网络,侵删)
gcc -o simple_get simple_get.c -lcurl
./simple_get

示例 2:发送一个 POST 请求(发送 JSON 数据)

这个例子演示了如何设置请求方法为 POST,并添加自定义的请求头(如 Content-Type: application/json)。

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    (void)userp;
    size_t realsize = size * nmemb;
    fwrite(contents, 1, realsize, stdout);
    return realsize;
}
int main(void) {
    CURL *curl;
    CURLcode res;
    const char *post_data = "{\"name\":\"John Doe\", \"email\":\"john.doe@example.com\"}";
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post");
        // 设置为 POST 请求
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
        // 设置 POST 数据大小,libcurl 可以自动计算,但显式设置是好的做法
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(post_data));
        // 设置自定义请求头
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        // 设置回调函数
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
        printf("Sending POST request with JSON data...\n");
        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }
        // 清理请求头
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    return 0;
}

C# HttpWebRequest 与 C libcurl 功能对比

为了让你更好地理解,这里有一个功能对比表格:

功能 C# HttpWebRequest C libcurl C libcurl 实现方式
初始化 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); CURL *curl = curl_easy_init(); curl_easy_init()
设置 URL req.RequestUri = new Uri(url); curl_easy_setopt(curl, CURLOPT_URL, url); CURLOPT_URL
GET 请求 (默认为 GET) (默认为 GET) 无需特殊设置
POST 请求 req.Method = "POST"; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); CURLOPT_POSTFIELDS
设置请求头 req.Headers.Add("Content-Type", "application/json"); struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Header-Name: Value");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_slist_appendCURLOPT_HTTPHEADER
获取响应状态码 int statusCode = (int)req.GetResponse().StatusCode; long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
CURLINFO_RESPONSE_CODE
读取响应体 using (var stream = response.GetResponseStream())
{ using(var reader = new StreamReader(stream)) ... }
size_t WriteCallback(void *data, size_t size, size_t nmemb, void *userp)
fwrite(data, size, nmemb, stdout);
CURLOPT_WRITEFUNCTION 回调
执行请求 using (var response = (HttpWebResponse)req.GetResponse()) curl_easy_perform(curl); curl_easy_perform()
清理资源 using 语句自动处理 curl_easy_cleanup(curl);
curl_global_cleanup();
curl_easy_cleanup()curl_global_cleanup()

高级功能和注意事项

  • SSL/TLS (HTTPS): libcurl 默认支持 HTTPS,如果需要自定义证书或验证逻辑,可以使用 CURLOPT_SSL_VERIFYPEERCURLOPT_SSL_VERIFYHOST 等选项。
  • 超时设置: 使用 CURLOPT_TIMEOUT (总超时) 和 CURLOPT_CONNECTTIMEOUT (连接超时) 来防止请求无限期挂起。
  • 错误处理: curl_easy_perform() 返回 CURLcode,你需要检查它是否为 CURLE_OKcurl_easy_strerror() 可以将错误码转换为可读的字符串。
  • 内存管理: 在示例中,我们直接将数据写入文件(stdout),在实际应用中,你可能需要将响应数据保存在内存缓冲区中,这需要你在 WriteCallback 中动态分配内存,并在请求结束后由主程序释放,这会增加内存管理的复杂性。
  • 多线程: libcurl 的 easy 接口不是线程安全的,如果你想在多线程环境中使用,每个线程都必须有自己的 CURL * 句柄,或者,你可以使用 curl_multi 接口,它被设计用于在单个线程中管理多个并发连接。

虽然 C 语言没有像 C# 那样封装好的 HttpWebRequest,但通过使用 libcurl 库,你可以实现所有常见的 HTTP 请求功能,包括 GET、POST、自定义请求头、处理响应、支持 HTTPS 等,libcurl 的学习曲线比 HttpWebRequest 稍陡峭,因为它更底层,需要你手动处理回调函数和内存管理,但它提供了无与伦比的灵活性和强大的功能,是 C 语言网络编程的首选工具。

-- 展开阅读全文 --
头像
C语言SetWindowText如何修改窗口标题?
« 上一篇 2025-12-10
C语言如何正确使用OpenClipboard函数?
下一篇 » 2025-12-10

相关文章

取消
微信二维码
支付宝二维码

目录[+]