【问题标题】:Libcurl progress callback not working with multiLibcurl 进度回调不适用于多
【发布时间】:2018-02-06 13:37:04
【问题描述】:

我正在尝试使用 C++ 中的 libcurl 管理下载进度。 我已经设法用 curl_easy 做到了这一点,但 curl_easy 的问题是它会阻塞程序,直到发出请求为止。

我需要使用 curl_mutli,所以 http 请求是异步的,但是当我尝试更改为 curl_multi 时,我的进度功能停止工作。

我有以下 curl_easy 请求代码:

int progressFunc(void* p, double TotalToDownload, double NowDownloaded, double TotalToUpload, double NowUploaded) {
    std::cout << TotalToDownload << ", " << NowDownloaded << std::endl;
    return 0;
}

FILE* file = std::fopen(filePath.c_str(), "wb");

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);

curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progressFunc);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);

CURLcode res = curl_easy_perform(curl);

完美运行并将下载进度打印到控制台。

但是,当尝试修改此代码以改用 curl_multi 时,文件无法正确下载(显示 0 字节)并且下载进度回调函数仅显示 0, 0

FILE* file = std::fopen(filePath.c_str(), "wb");

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);

curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progressFunc);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
curl_multi_add_handle(curlm, curl);

int runningHandles;
CURLMcode res = curl_multi_perform(curlm, &runningHandles);

【问题讨论】:

    标签: c++ libcurl


    【解决方案1】:

    TL; DR:你应该在循环中调用curl_multi_perform。如果你不使用事件循环和 poll/epoll,你应该坚持在单独的线程中使用curl_easy


    curl_multi API 的重点不是阻塞:您可以使用epoll 或类似的方法来监视 curl 的非阻塞套接字并在每次有数据到达时调用 curl_multi_perform,而不是在一次调用中神奇地下载整个文件网络。当你使用它的多模式时,curl 本身不会启动任何内部线程,也不会监控它的套接字——你应该自己做。这允许编写高性能的事件循环,在同一个线程中同时运行多个 curl 传输。需要它的人通常已经拥有必要的工具,或者可以轻松地自己编写。

    第一次调用curl_multi_perform 时,它很可能会在 DNS 解析完成之前和/或在远程端接受 TCP 连接之前返回。因此,在第一次调用中传输的有效负载数据量确实为 0。根据服务器配置,第二次调用也可能不会传输任何有效负载。 “有效负载”是指实际的应用程序数据(与 DNS 请求、SSL 协商、HTTP 标头和 HTTP2 帧元数据相反)。

    要真正完成传输,您必须反复调用 epoll_wait、curl_multi_perform 和许多其他函数,直到完成。 Curl's corresponding example 在完成一次传输后停止,但实际上创建一个永久运行的线程更有利,该线程处理应用程序生命周期内的所有 HTTP 传输。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 2015-11-27
      • 2018-04-07
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多