在做更新,在测试异常的时候,在下载过程中,发现如果直接系统禁用了网络,会报错误,可以捕获。但是如果是第三方软件限制程序联网,问题来了。
程序会一直在那里等待,没有异常,也不发送QNetworkAccessManager::finsh和QNetworkReply::error和QNetworkReply::finsh信号。
所以动念头为下载加个超时,但是QNetworkAccessManager,QNetworkReply和QNetworkRequest都没有相关的设置函数。其实仔细想一下,也没有办法直接提供超时,因为下载的文件有大有小,网络有快有慢,什么才算超时呢。只有自己想办法添加了。因为这个异常必须想办法发现并处理它,那么问题就必须要解决了。
先说下我的解决思路,利用QNetworkReply::downloadProgress 信号来实现,自己记录一段时间里的下载字节数,用定时器去定期检测,如果一段时间了,一点多余的下载都没有,那么我就认为网络超时异常了。
下面就上代码,自己简单用代码描述下:
声明:
class NetWorkDownload : public QObject { Q_OBJECT public: explicit NetWorkDownload(QObject *parent = 0); signals: void timeOut(); //····你的其他需要传递出去的信号 public slots: void startDownload(const QString & url); protected slots: void handleReply(QNetworkReply * rep);//处理下载完成的数据 void handSize(qint64 size, qint64 all); void handleTimeOut(); private: QNetworkAccessManager manger; int fileDownSize,//已经下载的字节数 lastDownSize;//定时器上次下载的字节数 QTimer tm;//定时器 };
实现:
NetWorkDownload::NetWorkDownload(QObject *parent) : QObject(parent) { //这个connect你也可以用QNetworkReply来链接,QNetworkReply::finsh,QNetworkReply::readyReady这些信号。 connect(&manger,&QNetworkAccessManager::finished,this,&NetWorkDownload::handleReply); connect(&tm,&QTimer::timeout,this,&NetWorkDownload::timeOut); } void NetWorkDownload::startDownload(const QString & url) { QNetworkRequest req; req.setUrl(QUrl(url)); auto rep = manger.get(req); connect(rep,&QNetworkReply::downloadProgress,this,&NetWorkDownload::handSize); //启动超时定时,30s。 if (tm.isActive()) tm.stop(); tm.start(30000); } void NetWorkDownload::handSize(qint64 size,qint64 /* all*/) { fileDownSize = size; } void NetWorkDownload::handleReply(QNetworkReply *rep) { /* 下载完成的您的处理代码。 */ fileDownSize = 0; lastDownSize = 0; if (tm.isActive())//如果还在定时,就停止 tm.stop(); } void NetWorkDownload::timeOut() { if (lastDownSize != fileDownSize)//如果过了30s,一点字节也没有下载过来,认为超时了。 lastDownSize = fileDownSize; else emit timeOut(); }
不懂的了解下
新站 求换友链,http://huanglv.me/p 消灭星星
我加上了、、只是我用了缓存插件,部分页面可能需要等会刷新缓存、、、
没玩过。
C++的东西、、、哈哈、、
代码好熟悉,又感觉逻辑好难。
这个逻辑不难的啊?只是定时器判断、、全异步而已、、
学习了
客气了、、我也菜鸟的、、
来学习的
客气了、、我也菜鸟的、、
QNetworkAccessManager manager_; QString url = QString(“https://api.shanbay.com/bdc/search/?word=%1”).arg(word); QNetworkRequest request; request.setUrl(QUrl(url)); QString tokenStr = QString(“Bearer %1”).arg(“kIFgt2b3QJwkmZ8hpi0QwvCCs6m59c”); request.setRawHeader(“Authorization”,tokenStr.toLatin1()); QNetworkReply* reply = manager_.get(request); QEventLoop loop; QObject::connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit())); QTimer::singleShot(3000, &loop, SLOT(quit())); loop.exec(); QByteArray data = reply->readAll(); if (!data.isEmpty()) { QString text = QString::fromUtf8(data); bool s = false; QtJson::JsonObject json = QtJson::parse(text, s).toMap(); if (s) { if (json.contains(“data”)) { QtJson::JsonObject dataObj = json[“data”].toMap(); QString cnValue = dataObj[“definition”].toString(); std::cout<< cnValue.toLocal8Bit().data() << std::endl; } QString myJson = QtJson::serializeStr(json); std::cout<< myJson.toLocal8Bit().data() << std::endl; makeTree(json); return myJson; } }//———————————————————————————//在知乎上看到你的回答,来你博客看一下。嘻嘻//我一般这样干,用eventloop来搞个同步 QNetworkReply* reply = manager_.get(request); QEventLoop loop; QObject::connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit())); QTimer::singleShot(3000, &loop, SLOT(quit())); loop.exec(); QByteArray data = reply->readAll(); if (!data.isEmpty()) { // somthing }
用QEventLoop 是最简单明了的方式、、但是在下载文件的时候,特别是连续下很多文件,你没法事先获取文件大小和用户的网络速度的,用这种估值的办法就不大现实了、、我这个是在做一个更新程序的时候遇到的,更新的文件中最大的一个是40多M的、、不能一次阻塞等他下完的、、就是放到单独线程中,时间也是不可估量的、、只有异步的方式处理、、、
看了好文章江南留言是美德 三亚婚纱摄影哪家好 http://www.timi520.com 切看切珍惜
看晕过去了!
这个稍微有点专业、、哈哈、、
超时提醒
第一次来你博客呢,网站做的不错哦,默默关注了。求交往啊,博主,求回访www.aiyw.net
QT的超时,reply默认情况下,会一直读取数据,直到读取完成吗?会不会出现还没有读取完数据,就断掉了
确实是一个好的想法,学习了。
此处,存在疑问,如果当前获取数据超时,那么应该怎样操作中断当前的数据获取呢?
求教,谢谢!