如何使 libcurl C++ 调用超时和/或知道调用中何时发生超时

Posted

技术标签:

【中文标题】如何使 libcurl C++ 调用超时和/或知道调用中何时发生超时【英文标题】:How to timeout a libcurl C++ call and/or know when a timeout has happened in the call 【发布时间】:2011-11-10 05:09:53 【问题描述】:

我正在尝试使用我的 C++ 程序下载远程 html 页面,但是某些 URL 会发生超时,但我不知道如何处理,所以程序将无限期挂起。

virtual void downloadpage(string pageaddress) 
    CURL *curl;
        CURLcode informationdownloaded;
        curl = curl_easy_init();
        if (curl)  
            curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13");
            curl_easy_setopt(curl, CURLOPT_URL, pageaddress.c_str());
            curl_easy_setopt(curl, CURLOPT_HEADER, 0);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writepageinformation);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pageinformation);
            informationdownloaded = curl_easy_perform(curl);
            curl_easy_cleanup(curl);
    

这是我通过“writepageinformation”函数将页面的html源下载到名为“pageinformation”的字符串变量的函数。

【问题讨论】:

【参考方案1】:

使用 CURLOPT_TIMEOUT 选项?

使用 CURLOPT_PROGRESSFUNCTION 回调并在您认为足够时停止操作?

使用 CURLOPT_LOWSPEED 选项或类似选项使其取决于传输速率。

【讨论】:

【参考方案2】:
informationdownloaded = curl_easy_perform(curl);

您还可以为下载指定超时时间

curl_easy_setopt(hCurl, CURLOPT_TIMEOUT, iTimeoutSeconds); // timeout for the URL to download

在下载整个文件之前,这是一个阻塞调用。 如果您有兴趣中断被阻止的调用(用于终止信号),请安装进度回调,如下所示

curl_easy_setopt(hCurl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(hCurl, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(hCurl, CURLOPT_PROGRESSDATA, this);

static int progress_callback(void *clientp,
                           double dltotal,
                           double dlnow,
                           double ultotal,
                           double ulnow)

    CLASS &obj = *(CLASS*)clientp;


    if (obj.exit)
      return 1; // if u want the signal curl to unblock and return from curl_easy_perform

    return 0; // if u want the callback to continue

【讨论】:

请注意,TIMEOUT 可能控制了连接后的下载时间,而Connection 进程挂起本身有一个单独的超时参数,这种情况更常见。请参阅 CURLOPT_CONNECTTIMEOUT。【参考方案3】:

除了使用CURLOPT_TIMEOUT 的其他建议外,您还可以定义超时,您应该只检查curl_easy_perform 的返回值,因为它是一个阻塞调用。这里是libcurl的doc/examples/getinfo.c稍作修改的版本,

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>

int main(int argc, char* argv[])

  CURL *curl;
  CURLcode res;

  if (argc != 2) 
    printf("Usage: %s <timeoutInMs>\n", argv[0]);
    return 1;
  

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/ip");
  curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, atol(argv[1]));

  res = curl_easy_perform(curl);

  if (CURLE_OK == res)
    printf("Success.\n");
  else if (CURLE_OPERATION_TIMEDOUT == res)
    printf("Operation timed out.\n");

  curl_easy_cleanup(curl);
  return 0;

【讨论】:

以上是关于如何使 libcurl C++ 调用超时和/或知道调用中何时发生超时的主要内容,如果未能解决你的问题,请参考以下文章

linux c++中要如何调用一个http接口

如何正确安装 libcurl 以在 Visual Studio 2017 中使用?

如何修复连接超时,cURL 错误 28?

如何使用 NSURLConnection (NSMutableRequest) 超时

C++ Boost ASIO:如何读取/写入超时?

如何将 libcurl 与 dev c++ 静态链接?