Persistent connection using QNetworkAccessManager in Qt

I am trying to maintain a constant connection between the client and the remote server using Qt. My portion is beautiful. I am doing my client side in Qt. Here I will use the QNetworkAccessManager to query the server with the get method (part of the QNetworkRequest method). I will be able to send and receive requests.

But after a while (approximately ~ 2 min), the client connects the server, the connection closes, sending the request automatically. I think QNetworkAccessManager sets a timeout for this connection. I want to maintain a constant connection between the ends.

Is my approach right, if not, can someone direct me on the right path?

+5
source share
2 answers

This question is interesting, so do some research. I set up a nginx server with a long wait time and wrote the simplest Qt application:

 QApplication a(argc, argv); QNetworkAccessManager manager; QNetworkRequest r(QUrl("http://myserver/")); manager.get(r); return a.exec(); 

In addition, I used the following command (in the Linux console) to monitor connections and see if the problem was reproducing at all:

 watch -n 1 netstat -n -A inet 

I quickly looked at the sources of Qt and found that it uses QTcpSocket and closes it in QHttpNetworkConnectionChannel::close . So I opened the debugger console ( Window → Views → Debugger log in Qt Creator) and added a breakpoint when the process was paused:

 bp QAbstractSocket::close 

Note: this is for cdb (MS debugger), other debuggers require other commands. Another note: I use Qt with debugging information, and this approach may work without it.

After two minutes of waiting, I received feedback from a call to close() !

 QAbstractSocket::close qabstractsocket.cpp 2587 0x13fe12600 QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate qhttpnetworkconnection.cpp 110 0x13fe368c4 QHttpNetworkConnectionPrivate::`scalar deleting destructor' untitled 0x13fe3db27 QScopedPointerDeleter<QObjectData>::cleanup qscopedpointer.h 62 0x140356759 QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData>>::~QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData>> qscopedpointer.h 99 0x140355700 QObject::~QObject qobject.cpp 863 0x14034b04f QHttpNetworkConnection::~QHttpNetworkConnection qhttpnetworkconnection.cpp 1148 0x13fe35fa2 QNetworkAccessCachedHttpConnection::~QNetworkAccessCachedHttpConnection untitled 0x13fe1e644 QNetworkAccessCachedHttpConnection::`scalar deleting destructor' untitled 0x13fe1e6e7 QNetworkAccessCachedHttpConnection::dispose qhttpthreaddelegate.cpp 170 0x13fe1e89e QNetworkAccessCache::timerEvent qnetworkaccesscache.cpp 233 0x13fd99d07 (next lines are not interesting) 

The class responsible for this action is QNetworkAccessCache . It sets timers and ensures that its objects will be deleted if QNetworkAccessCache::Node::timestamp in the past. And these objects are HTTP connections, FTP connections, and credentials.

Further, what is timestamp ? When an object is released, its timestamp is calculated as follows:

 node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime); 

And ExpiryTime = 120 hard-coded.

All classes involved are private, and I have not found a way to prevent this. Therefore, it is easiest to send keep-alive requests every minute (at least now you know that 1 minute is safe enough), since the alternative is to rewrite the Qt code and compile the user version.

+2
source

I would say that by definition, a 2-minute connection to a timeout qualifies as permanent. I mean, if it was not persistent, you would need to reconnect to each request. 2 minutes is quite generous compared to some other programs. But he is set to end the timeout after a period of inactivity and that is a good thing that should not be surprising. Some software allows you to change the timeout period, but from the Pavel study it will appear in the case of Qt, the timeout is hard-coded.

Fortunately, the solution is simple, just set a timer to send a heartbeat (just a dummy request, do not confuse with the "heartbeat network") every 1 minute or so to keep in touch. Turn off the timer before using the connection, and after you end the connection, restart the timer.

0
source

All Articles