β

libcurl中curl_easy_perform卡死问题

Harries Blog™ 507 阅读

LibCurl使用阻塞的方式来进行 http 下载 ,curl_easy_perform执行后,程序会在这里阻塞等待下载结束(成功OR失败),此时若下载一段 时间 后出现网络异常,curl_easy_perform不会返回失败,整个 线程 阻塞卡死。

问题分析

复现:连接无线网络,然后执行curl_easy_perform下载,下载过程中,断开无线网络,curl_easy_perform卡死,阻塞整个线程。

原因:当断开无线网络时,使用命令行netstat ano | find str ‘连接 ip ’, 可以发现LibCurl的http连接并没有断开(不知道是不是 windows 系统的bug),如果将CURLOPT_TIMEOUT设置为无限等待,curl_easy_perform便会一直阻塞住线程。

解决方案

1、如果我们不将CURLOPT_TIMEOUT设置为无限等待,是不会出现上面问题,curl_easy_perform会在执行一段时间(由CURLOPT_TIMEOUR设置),结束并返回失败,但是如果设置合适的CURLOPT_TIMEOUT是个问题。

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0); // blocking forever, cannot find a suitable value

2、使用multi模式下载, 而不使用easy模式, 此方法的唯一好处就是multi并不会阻塞, 而是立即返回. 但是缺点是带来了问题, 其一就是需要自己去阻塞, 当我们需要返回时再返回, 其二还需要启动一个线程, 需要自己控制整个过程的节奏。

3、在下载中, 另起一个线程, 若发现下载状态卡死(可以通过定期检查文件大小来实现), 则从外部中断下载线程. 此方法需另起线程, 而且直接中断线程, 会给整个程序带来不稳定。

4、设置CURLOPT_TIMEOUT为30s,以30s为间隔断点续传。

5、使用CURLOPT_LOW_SPEED_LIMIT, CURLOPT_LOW_SPEED_TIME

res = curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1024L);
res = curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 30L);

6、使用CURLOPT_PROGRESSFUNCTION设置进度表回调函数,可以在该回调函数内部检测下载是否出错,如果出现就中断curl_easy_perform,返回下载错误。

#include <curl/curl.h>
int progress_callback(void *clientp,   double dltotal,   double dlnow,   double ultotal,   double ulnow);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSFUNCTION, progress_callback);

原文 http://JerkWisdom. git hub.io/developing/3rdparty/ lib curl-curl_easy_perform-blocking-problem/

PS:如果您想和业内技术大牛交流的话,请加qq群(521249302)或者关注微信公众 号(AskHarries),谢谢!

转载请注明原文出处: Harries Blog™ » libcurl中curl_easy_perform卡死问题

作者:Harries Blog™
追心中的海,逐世界的梦
原文地址:libcurl中curl_easy_perform卡死问题, 感谢原作者分享。

发表评论