libcurl multi接口

680 阅读1分钟
const char* url = "http://www.google.com";
const int count = 3;
// 暂时是所有请求的结果都附加到stream末尾,实际上应该是每个request单独设置一个stream
std::stringstream data_to_write_stream;

size_t write_data(void* buffer, size_t size, size_t count, void* stream) {

    auto* out_stream = (std::stringstream*) stream;
    (*out_stream) << std::string((char*) buffer, size * count);

    return size * count;
}

int main() {
    CURLM* multi_handle = curl_multi_init();

    for (int i = 0; i < count; ++i) {
        struct curl_slist* headers = nullptr;
        std::string header_str;

        CURL* easy_handle = curl_easy_init();
        curl_easy_setopt(easy_handle, CURLOPT_URL, url);
        curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &data_to_write_stream);
        curl_multi_add_handle(multi_handle, easy_handle);
    }

    // 等待所有的easy handle执行完毕
    int running_handlers = 0;
    do {
        int prev_running_handlers = running_handlers;

        // 在multi_handle中轮询所有的easy_handle,会阻塞,直到检测到有handle发生活动或超过设定的时间
        // @param updated_easy_handle_nums为发生了活动的easy handle的数量
        int updated_easy_handle_nums;
        curl_multi_wait(multi_handle, nullptr, 0, 1200, &updated_easy_handle_nums);

        // curl_multi_perform是非阻塞的
        curl_multi_perform(multi_handle, &running_handlers);

        // 当running_handlers改变的时候,就说明存在request已经执行完毕了,可以获取这些request的相关信息然后进行相关清理工作了
        if (prev_running_handlers != running_handlers) {
            do {
                int msgs_left = 0;
                CURLMsg* curl_msg = curl_multi_info_read(multi_handle, &msgs_left);
                if (curl_msg == nullptr) {
                    break;
                }
                // 在这里获取request的详细连接信息
                if (curl_msg->msg == CURLMSG_DONE) {
                    int http_status_code = 0;
                    curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_RESPONSE_CODE, &http_status_code);
                    char* effective_url = nullptr;
                    curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_EFFECTIVE_URL, &effective_url);
                    std::cout << "effective_url->" << effective_url
                              << ", http_status_code->" << http_status_code
                              << ", result->" << curl_easy_strerror(curl_msg->data.result) << std::endl;
                    curl_multi_remove_handle(multi_handle, curl_msg->easy_handle);
                    curl_easy_cleanup(curl_msg->easy_handle);
                }
            } while (true);
        }
    } while (running_handlers > 0);

    curl_multi_cleanup(multi_handle);

    std::cout << data_to_write_stream.str() << std::endl;
    return 0;
}