C++使用libcurl实现HTTP请求的基础准备
要在C++中使用libcurl库发送HTTP请求,首先需要完成库的安装与项目配置。在Linux系统中可以通过包管理器直接安装,比如Ubuntu系统执行sudo apt-get install libcurl4-openssl-dev即可完成安装。Windows系统可以下载libcurl的预编译库,或者在项目中通过vcpkg等包管理工具引入。配置完成后,代码中需要包含curl的头文件,并且链接对应的库文件。

libcurl的基本使用流程
无论发送GET还是POST请求,libcurl的核心使用流程都包含几个固定步骤:初始化curl句柄、设置请求相关参数、执行请求、处理响应数据、清理句柄释放资源。下面是通用的流程框架代码:
#include <curl/curl.h>
#include <iostream>
#include <string>
// 回调函数,用于处理响应数据
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
int main() {
// 初始化curl全局环境
CURLcode globalInitRes = curl_global_init(CURL_GLOBAL_DEFAULT);
if (globalInitRes != CURLE_OK) {
std::cerr << "curl全局初始化失败: " << curl_easy_strerror(globalInitRes) << std::endl;
return -1;
}
// 创建curl句柄
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "创建curl句柄失败" << std::endl;
curl_global_cleanup();
return -1;
}
std::string responseData; // 存储响应数据
// 设置回调函数,将响应数据存入responseData
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 这里后续会设置请求URL和请求类型相关参数
// 执行请求
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "请求执行失败: " << curl_easy_strerror(res) << std::endl;
} else {
// 获取HTTP响应状态码
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "HTTP响应状态码: " << httpCode << std::endl;
std::cout << "响应数据: " << responseData << std::endl;
}
// 清理句柄
curl_easy_cleanup(curl);
// 清理全局环境
curl_global_cleanup();
return 0;
}
使用libcurl发送GET请求
GET请求的参数通常拼接在URL后面,设置好请求URL后直接执行即可。如果需要设置请求超时、添加自定义请求头,也可以通过对应的选项配置。
简单GET请求实现
下面的代码实现了向ipipp.com的测试接口发送GET请求,获取接口返回的数据:
#include <curl/curl.h>
#include <iostream>
#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "创建curl句柄失败" << std::endl;
return -1;
}
std::string responseData;
// 设置GET请求的URL,参数拼接在URL后面
curl_easy_setopt(curl, CURLOPT_URL, "https://ipipp.com/api/test?name=test&age=20");
// 设置响应数据回调函数
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 设置请求超时时间为5秒
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "GET请求失败: " << curl_easy_strerror(res) << std::endl;
} else {
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "GET请求响应状态码: " << httpCode << std::endl;
std::cout << "GET请求响应数据: " << responseData << std::endl;
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
带自定义请求头的GET请求
如果接口需要特定的请求头,比如需要携带认证token,可以通过CURLOPT_HTTPHEADER选项设置:
#include <curl/curl.h>
#include <iostream>
#include <string>
#include <list>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (!curl) {
return -1;
}
std::string responseData;
curl_easy_setopt(curl, CURLOPT_URL, "https://ipipp.com/api/user/info");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 构建自定义请求头列表
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "Authorization: Bearer test_token_123456");
// 设置自定义请求头
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "响应状态码: " << httpCode << std::endl;
std::cout << "响应数据: " << responseData << std::endl;
}
// 释放请求头列表
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
使用libcurl发送POST请求
POST请求需要设置请求方法为POST,并且根据接口要求设置请求体的数据格式,常见的格式有表单格式和JSON格式。
发送表单格式的POST请求
表单格式的POST请求数据需要按照key=value的形式拼接,并且设置CURLOPT_POSTFIELDS选项:
#include <curl/curl.h>
#include <iostream>
#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (!curl) {
return -1;
}
std::string responseData;
// 设置POST请求的URL
curl_easy_setopt(curl, CURLOPT_URL, "https://ipipp.com/api/login");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 设置POST请求的表单数据
std::string postFields = "username=test_user&password=test_pass123";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields.c_str());
// 表单格式不需要额外设置Content-Type,libcurl会自动处理
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "POST表单请求响应状态码: " << httpCode << std::endl;
std::cout << "响应数据: " << responseData << std::endl;
} else {
std::cerr << "POST请求失败: " << curl_easy_strerror(res) << std::endl;
}
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
发送JSON格式的POST请求
如果接口要求请求体为JSON格式,需要手动设置Content-Type请求头,并且将JSON字符串作为POST数据传入:
#include <curl/curl.h>
#include <iostream>
#include <string>
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (!curl) {
return -1;
}
std::string responseData;
curl_easy_setopt(curl, CURLOPT_URL, "https://ipipp.com/api/submit_data");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
// 构建JSON格式的请求数据
std::string jsonData = "{"name":"test","age":25,"hobby":["reading","coding"]}";
// 设置POST数据
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str());
// 设置JSON格式的请求头
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
std::cout << "POST JSON请求响应状态码: " << httpCode << std::endl;
std::cout << "响应数据: " << responseData << std::endl;
} else {
std::cerr << "POST请求失败: " << curl_easy_strerror(res) << std::endl;
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
常见问题与注意事项
- 每次使用完curl句柄后必须调用
curl_easy_cleanup释放资源,避免内存泄漏 - 全局初始化函数
curl_global_init只需要调用一次,程序退出前调用curl_global_cleanup即可 - 如果请求HTTPS接口,libcurl默认会验证证书,如果需要跳过证书验证,可以设置
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L),但生产环境不建议这么做 - POST请求的数据如果是二进制内容,需要设置
CURLOPT_POSTFIELDSIZE指定数据长度,避免数据被截断
总结
通过libcurl库在C++中实现HTTP请求的步骤非常清晰,核心就是初始化、配置参数、执行请求、处理响应、清理资源几个环节。GET请求只需要拼接好带参数的URL,POST请求则需要根据数据格式设置对应的请求体和请求头。开发者可以根据实际接口的要求,灵活调整请求参数和配置选项,满足不同的网络请求需求。