HTTP 客户端在 C++ 中:从 A 到 Z 正确发起请求
在现代编程世界中,通过 HTTP 协议与远程服务器交互是一项基本任务。无论是从 API 获取数据、发送表单还是下载文件——掌握 HTTP 请求的处理能力对每位 C++ 开发者来说都是必要的。在本文中,我们将详细讲解如何在 C++ 中创建一个完整的 HTTP 客户端,介绍流行的库和最佳实践。
为什么需要 C++ 的 HTTP 客户端?
与内置 HTTP 库的语言(如 Python、JavaScript)不同,C++ 的标准库中没有用于处理 HTTP 的标准工具。但这并不是问题,因为有多个经过时间考验的强大解决方案:
- libcurl — 最流行且功能强大的 URL 处理库
- cpprestsdk (Casablanca) — 微软开发的现代异步库
- Boost.Beast — 基于 Boost.Asio 的低级处理库
在本文中,我们将重点介绍 libcurl 和 cpprestsdk,因为它们是最常用的解决方案。
libcurl 基础
libcurl 是一个经过时间考验的库,支持多种协议,包括 HTTP/1.1、HTTP/2、FTP 等。它用 C 语言编写,但拥有出色的 C++ 绑定。
安装 libcurl
安装 libcurl 取决于您的操作系统:
# Ubuntu/Debian
sudo apt-get install libcurl4-openssl-dev
# macOS (通过 Homebrew)
brew install curl
# Windows (通过 vcpkg)
vcpkg install curl
使用 libcurl 发送简单的 GET 请求
我们从基本示例开始——发送 GET 请求并获取响应:
#include <iostream>
#include <curl/curl.h>
#include <string>
// 用于写入数据的回调函数
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
size_t totalSize = size * nmemb;
output->append(static_cast<char*>(contents), totalSize);
return totalSize;
}
int main() {
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "CURL 初始化错误" << std::endl;
return 1;
}
std::string response;
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "请求错误: " << curl_easy_strerror(res) << std::endl;
} else {
std::cout << "服务器响应:" << std::endl;
std::cout << response << std::endl;
}
curl_easy_cleanup(curl);
return 0;
}
发送带数据的 POST 请求
POST 请求用于向服务器发送数据。我们来看一个包含 JSON 数据的示例:
#include <iostream>
#include <curl/curl.h>
#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
size_t totalSize = size * nmemb;
output->append(static_cast<char*>(contents), totalSize);
return totalSize;
}
int main() {
CURL* curl = curl_easy_init();
if (!curl) return 1;
std::string response;
std::string jsonData = R"({"title": "foo", "body": "bar", "userId": 1})";
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
cur