How to set QNetworkReply timeout without external timer?
It's not possible without using a timer, but you don't have to explicitly write timer code. The functionality can be neatly packaged into a static function that acts as if the timeout was a settable property of the reply - see example below.
There are two issues:
How to handle a timeout on a request that is in progress.
How to determine whether a network request has begun processing. This problem is addressed in this question.
A simple timeout handler could be implemented as below (derived from this answer). The code is portable across Qt 4 and Qt 5.
You have a choice between abort
-ing the request on timeout (the default), or close
-ing it. The former releases network resources immediately, the latter allows the request to finish but discards any data received and is mostly useful with upload requests.
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();
}
}
};
Use:
QNetworkAccessManager networkAccessManger;
QNetworkReply* reply =
networkAccessManger.get(QNetworkRequest(QUrl("https://www.google.com")));
ReplyTimeout::set(reply, 100);
with Qt 5.15 it should be a built-in feature - just found out that a 10 yrs old bug is fixed :) https://codereview.qt-project.org/c/qt/qtbase/+/278064