为QNetworkAccessManager添加超时提醒

在做更新,在测试异常的时候,在下载过程中,发现如果直接系统禁用了网络,会报错误,可以捕获。但是如果是第三方软件限制程序联网,问题来了。

程序会一直在那里等待,没有异常,也不发送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();
}

 

评论已关闭。