C++ libcurl如何从curl multi handle中获取多请求完成后的响应数据
libcurl 多请求传输模式下获取完整响应的实现方式
libcurl 没有提供和 PHP 中 multi_get_content() 功能完全对应的直接获取响应的接口,响应内容需要你提前为每个 CURL* 类型的 easy handle 配置回调存储,传输完成后从自定义存储中读取即可,具体实现步骤如下:
实现步骤
- 首先定义自定义响应存储结构,用于存储每个请求的响应体、HTTP 状态码等信息
struct HttpResponse { std::string body; // 存储完整响应体 long http_status = 0; // 存储HTTP响应状态码 CURLcode curl_err = CURLE_OK; // 存储libcurl执行错误码 };
- 实现libcurl要求格式的写回调函数,libcurl收到响应数据时会自动调用该函数,把数据写入到你自定义的结构中
size_t write_data_cb(void* buffer, size_t size, size_t nmemb, void* user_ptr) { size_t data_len = size * nmemb; HttpResponse* resp = static_cast<HttpResponse*>(user_ptr); resp->body.append(static_cast<char*>(buffer), data_len); return data_len; }
- 初始化每个请求的easy handle时,绑定回调和对应的响应存储实例,再加入multi handle
// multi handle初始化(你应该已经完成了这一步) CURLM* multi_handle = curl_multi_init(); // 存储easy handle和对应响应实例的映射关系,方便后续读取 std::unordered_map<CURL*, HttpResponse*> handle_map; // 单个请求的初始化逻辑(批量创建多个easy handle时重复这段即可) CURL* easy_handle = curl_easy_init(); HttpResponse* resp = new HttpResponse(); curl_easy_setopt(easy_handle, CURLOPT_URL, "你的请求地址"); // 绑定写回调 curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data_cb); // 把当前请求对应的响应存储实例传给回调 curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, resp); // 加入multi队列 curl_multi_add_handle(multi_handle, easy_handle); // 保存映射关系 handle_map[easy_handle] = resp;
- multi传输完成后,遍历CURLMsg获取执行状态的同时,直接从映射的响应实例中取完整内容
int pending_msg_cnt; while (CURLMsg* msg = curl_multi_info_read(multi_handle, &pending_msg_cnt)) { if (msg->msg == CURLMSG_DONE) { CURL* done_handle = msg->easy_handle; HttpResponse* resp = handle_map[done_handle]; resp->curl_err = msg->data.result; if (resp->curl_err == CURLE_OK) { // 读取HTTP状态码 curl_easy_getinfo(done_handle, CURLINFO_RESPONSE_CODE, &resp->http_status); // 此处resp->body就是当前请求的完整响应体,可以直接使用 } // 资源清理 curl_multi_remove_handle(multi_handle, done_handle); curl_easy_cleanup(done_handle); delete resp; } } // 所有请求处理完成后清理multi handle curl_multi_cleanup(multi_handle);
注意事项
- 写回调的返回值必须等于实际写入的字节数,也就是等于传入的
size * nmemb,如果返回值不一致,libcurl会认为写入出错,终止当前请求。 - 每个easy handle必须对应独立的
HttpResponse实例,不要多个handle共用同一个存储地址,会导致响应数据串扰。 - 如果需要获取响应头内容,可以额外配置
CURLOPT_HEADERFUNCTION和CURLOPT_HEADERDATA,实现逻辑和获取响应体完全一致。
内容的提问来源于stack exchange,提问作者noah
相关产品推荐
相关产品推荐

