Diese Frage ist interessant, also lasst uns etwas recherchieren. Ich habe einen nginx Server mit großen Keep-Alive-Timeout auf und schrieb die simpliest Qt-Anwendung:
QApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest r(QUrl("http://myserver/"));
manager.get(r);
return a.exec();
Auch habe ich den folgenden Befehl ein (in Linux-Konsole) Verbindungen zu überwachen und zu prüfen, ob das Problem überhaupt wiedergibt:
Ich schaute schnell auf Qt Quellen und stellte fest, dass es QTcpSocket
verwendet und schließt es in QHttpNetworkConnectionChannel::close
. Also öffnete ich den Debugger-Konsole (Window → Views → Debugger log
in Qt Creator) und hat einen Haltepunkt, während der Prozess unterbrochen wurde:
bp QAbstractSocket::close
Hinweis: Dies ist für cdb (MS Debugger), andere Debugger benötigen andere Befehle. Noch ein Hinweis: Ich verwende Qt mit Debug-Informationen, und dieser Ansatz funktioniert möglicherweise nicht ohne.
Nach zwei Minuten Wartezeit habe ich das Backtrace der close()
Anruf!
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)
Die Klasse verantwortlich für diese Aktion ist QNetworkAccessCache
. Es stellt Timer ein und stellt sicher, dass seine Objekte gelöscht werden, wenn QNetworkAccessCache::Node::timestamp
in der Vergangenheit liegt. Und diese Objekte sind HTTP-Verbindungen, FTP-Verbindungen und Anmeldeinformationen.
Als nächstes, was ist timestamp
? Wenn das Objekt freigegeben wird, wird sein Zeitstempel in der folgenden Weise berechnet:
node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime);
Und ExpiryTime = 120
hartcodiert ist.
Alle beteiligten Klassen sind privat, und ich habe keine Möglichkeit gefunden, dies zu verhindern. So ist es viel einfacher, Keep-Alive-Anfragen jede Minute zu senden (zumindest wissen Sie jetzt, dass 1 Minute sicher genug ist), da die Alternative darin besteht, Qt-Code neu zu schreiben und eine benutzerdefinierte Version zu kompilieren.
scheint diese Frage für mich wirklich gültig zu sein. Wenn Sie eine Lösung finden, würden Sie gerne mit der Community teilen? Bitte geben Sie auch ein Code-Snippet an, damit SO-Ingenieure Ihnen mit Leichtigkeit helfen können. – Whoami
Warum implementieren Sie nicht einen Heartbeat, um die Verbindung aufrecht zu erhalten? – dtech
Wenn Ihr Server WebSockets unterstützt, können Sie http://doc.qt.io/qt-5/qtweb Sockets-Index.html für eine dauerhafte Verbindung zwischen Ihrem Client und Server auschecken. –