用libcurl发get请求最稳:需调用curl_global_init/cleanup,每个请求独立init,设url、超时、writefunction回调存响应体到std::string,避免ostringstream。

用 libcurl 发 GET 请求最稳
C++ 标准库不带 HTTP 客户端,libcurl 是事实标准,跨平台、成熟、可控。别碰那些封装过重的“C++ REST SDK”(比如微软那个已弃用的 cpprestsdk),编译麻烦、依赖多、报错信息反人类。
常见错误现象:CURLOPT_URL 没设对导致 CURLE_URL_MALFORMAT;忘了 curl_global_init(CURL_GLOBAL_DEFAULT) 直接 crash;没设 CURLOPT_FOLLOWLOCATION 被 302 重定向卡住。
- 必须在程序启动时调一次
curl_global_init(CURL_GLOBAL_DEFAULT),退出前调curl_global_cleanup() - 每个请求独立用
curl_easy_init(),别复用句柄做并发(除非你手动加锁并设CURLOPT_NOSIGNAL) - 响应体默认不返回,得用
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback)+ 自定义回调收数据 - 超时一定要设:
curl_easy_setopt(handle, CURLOPT_TIMEOUT, 10L),否则 DNS 卡死就真卡死了
std::string 接收响应体别用 std::ostringstream
很多示例教你在回调里往 std::ostringstream 写,看似简洁,实则隐藏内存重分配开销和线程安全陷阱——libcurl 回调可能被多次调用,std::ostringstream::str() 返回的是拷贝,不是引用。
正确做法是传一个 std::string* 进去,在回调里直接 ->append(ptr, size):
立即学习“C++免费学习笔记(深入)”;
size_t write_callback(void* ptr, size_t size, size_t nmemb, void* userdata) {
std::string* buf = static_cast<std::string*>(userdata);
size_t bytes = size * nmemb;
buf->append(static_cast<char*>(ptr), bytes);
return bytes;
}注意:ptr 不保证以 <p>注意:<code>ptr 不保证以 \0 结尾,别当 C 字符串用;如果服务端返回二进制(比如图片),std::string 完全能存,别硬转 std::string_view 或 std::vector<uint8_t></uint8_t> 增加复杂度。
std::string 完全能存,别硬转 std::string_view 或 std::vector<uint8_t></uint8_t> 增加复杂度。POST JSON 别手拼字符串,用 CURLOPT_POSTFIELDS + CURLOPT_HTTPHEADER
手动拼 "{\"name\":\"x\"}" 容易漏转义、编码错、少逗号。JSON 应该由序列化库生成,再喂给 curl。
常见错误现象:Content-Length 没匹配实际 body 长度导致 400;忘了设 application/json 导致后端解析失败;用 CURLOPT_POST 但没清空 CURLOPT_HTTPGET 状态位。
- 先用
nlohmann::json(或rapidjson)构造对象,再调.dump()得到std::string - 设 body:
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, json_str.c_str()) - 设 header:
struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); - 记得最后
curl_slist_free_all(headers),不然内存泄漏
Windows 上链接 libcurl 别漏 -lcurl -lws2_32 -lwldap32 -lwinmm
Linux/macOS 下通常只写 -lcurl 就够,Windows 需显式链接 Winsock 和 LDAP 库,否则链接时报 undefined reference to `WSAStartup@8' 或类似符号找不到。
MSVC 用户更麻烦:得确认用的是 libcurl 的 DLL 版还是静态版,静态版要加 CURL_STATICLIB 宏,否则 curl_global_init 找不到;DLL 版则必须把 libcurl.dll 放到 exe 同目录或 PATH 里,否则运行时报 “找不到指定模块”。
最容易被忽略的是:不同编译器(MSVC/MinGW)、不同运行时(MD/MT)、不同架构(x64/x86)的 libcurl 库不能混用。哪怕只差一个配置项,加载时就静默失败。










