如何在没有外部计时器的情况下设置 QNetworkReply 超时

How to set QNetworkReply timeout without external timer?

本文关键字:情况下 设置 QNetworkReply 超时 计时器 外部      更新时间:2023-10-16

是否可以为QNetworkReply设置超时,所以很长一段时间没有来自服务器的回复,它可以发出finished()信号?

不使用计时器是不可能的,但您不必显式编写计时器代码。该功能可以整齐地打包到一个静态函数中,该函数就像超时是回复的可设置属性一样 - 请参阅下面的示例。

有两个问题:

  1. 如何处理正在进行的请求超时。

  2. 如何确定网络请求是否已开始处理。此问题已在此问题中解决。

一个简单的超时处理程序可以实现如下(从这个答案派生)。该代码可在Qt 4和Qt 5之间移植。

您可以选择在超时时abort请求(默认值)或close请求。前者立即释放网络资源,后者允许请求完成,但丢弃收到的任何数据,并且对上传请求最有用。

class ReplyTimeout : public QObject {
    Q_OBJECT
public:
    enum HandleMethod { Abort, Close };
    ReplyTimeout(QNetworkReply* reply, const int timeout, HandleMethod method = Abort) :
        QObject(reply), m_method(method)
    {
        Q_ASSERT(reply);
        if (reply && reply->isRunning()) {
            m_timer.start(timeout, this);
            connect(reply, &QNetworkReply::finished, this, &QObject::deleteLater);
        }
    }
    static void set(QNetworkReply* reply, const int timeout, HandleMethod method = Abort)
    {
        new ReplyTimeout(reply, timeout, method);
    }
protected:
    QBasicTimer m_timer;
    HandleMethod m_method;
    void timerEvent(QTimerEvent * ev) {
        if (!m_timer.isActive() || ev->timerId() != m_timer.timerId())
            return;
        auto reply = static_cast<QNetworkReply*>(parent());
        if (reply->isRunning())
        {
            if (m_method == Close)
                reply->close();
            else if (m_method == Abort)
                reply->abort();
            m_timer.stop();
        }
    }
};

用:

QNetworkAccessManager networkAccessManger;
QNetworkReply* reply = 
  networkAccessManger.get(QNetworkRequest(QUrl("https://www.google.com")));
ReplyTimeout::set(reply, 100);

Qt 5.15中,它应该是一个内置功能 - 刚刚发现修复了一个10年前的错误:)https://codereview.qt-project.org/c/qt/qtbase/+/278064