Libcurl为一个免费开源的,客户端url传输库,本文主要分析使用过程中遇到的卡死问题。
问题描述
LibCurl使用阻塞的方式来进行http下载,curl_easy_perform执行后,程序会在这里阻塞等待下载结束(成功OR失败),此时若下载一段时间后出现网络异常,curl_easy_perform不会返回失败,整个线程阻塞卡死。
问题分析
复现:连接无线网络,然后执行curl_easy_perform下载,下载过程中,断开无线网络,curl_easy_perform卡死,阻塞整个线程。
原因:当断开无线网络时,使用命令行netstat ano | findstr ‘连接ip’, 可以发现LibCurl的http连接并没有断开(不知道是不是windows系统的bug),如果将CURLOPT_TIMEOUT设置为无限等待,curl_easy_perform便会一直阻塞住线程。
解决方案
1、如果我们不将CURLOPT_TIMEOUT设置为无限等待,是不会出现上面问题,curl_easy_perform会在执行一段时间(由CURLOPT_TIMEOUR设置),结束并返回失败,但是如果设置合适的CURLOPT_TIMEOUT是个问题。
1
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
int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
茶杯头甜蜜终章dlc 官方手机版v1.0.0.3
下载火柴人传说暗影格斗内置菜单 最新版v3.0.1
下载荒野乱斗测试服 安卓版v61.10.3
下载荒野乱斗彩虹服 安卓版v61.10.3
下载寒霜启示录 安卓版v1.25.10
寒霜启示录是一款生存模拟游戏,不少玩家可能对于末日都有着自己
末日城堡免广告版 安卓最新版v0.7.1
末日城堡免广告版是一款非常好玩的模拟经营类游戏,内部可以不看
甜蜜人生模拟器 最新版v1.4.5
甜蜜人生模拟器是一款非常好玩的模拟恋爱手游,玩家在这里能够对
武器锻造师内置功能菜单 v10.4
武器锻造师内置菜单版是游戏的破解版本,在该版本中为玩家提供了
开放空间overfield 安卓版v1.0.5
开放空间Overfield是一款箱庭养成经营手游,让你在广阔