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

时间:2016-05-25 18:00:58

标签: c++ qt

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

2 个答案:

答案 0 :(得分:4)

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

有两个问题:

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

  2. 如何确定网络请求是否已开始处理。 this question

  3. 解决了此问题

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

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

    class ReplyTimeout : public QObject {
      Q_OBJECT
      QBasicTimer m_timer;
      HandleMethod m_method;
    public:
      enum HandleMethod { Abort, Close };
      QReplyTimeout(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:
      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);
    

答案 1 :(得分:0)

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