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

Nya*_*uko 8 c++ qt

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

Rei*_*ica 6

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

有两个问题:

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

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

可以如下实现一个简单的超时处理程序(从此答案派生)。该代码可跨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();
  }
};
Run Code Online (Sandbox Code Playgroud)

使用:

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