Questa domanda è interessante, quindi facciamo qualche ricerca. Ho messo su un server nginx con grande timeout tenere in vita e ha scritto la più semplice applicazione Qt:
QApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest r(QUrl("http://myserver/"));
manager.get(r);
return a.exec();
Inoltre ho usato il seguente comando (in consolle Linux) per monitorare le connessioni e verificare se il problema riproduce affatto:
watch -n 1 netstat -n -A inet
Ho dato una rapida occhiata alle fonti Qt e ho scoperto che utilizza QTcpSocket
e lo chiude in QHttpNetworkConnectionChannel::close
. Così ho aperto la console debugger (Window → Views → Debugger log
in Qt Creator) e aggiunto un punto di interruzione, mentre il processo è stato messo in pausa:
bp QAbstractSocket::close
Nota: questo è per CDB (debugger MS), altri debugger richiede altri comandi. Un'altra nota: io uso Qt con informazioni di debug e questo approccio potrebbe non funzionare senza di esso.
Dopo due minuti di attesa ho avuto la backtrace della chiamata 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)
La classe responsabile di questa azione è QNetworkAccessCache
. Imposta i timer e si assicura che i suoi oggetti siano cancellati quando QNetworkAccessCache::Node::timestamp
è nel passato. E questi oggetti sono connessioni HTTP, connessioni FTP e credenziali.
Quindi, che cos'è timestamp
? Quando l'oggetto viene rilasciato, il suo timestamp viene calcolato nel seguente modo:
node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime);
E ExpiryTime = 120
è hardcoded.
Tutte le classi coinvolte sono private e non ho trovato alcun modo per impedire che ciò accada. Quindi è molto più semplice inviare richieste keep-alive ogni minuto (almeno ora sai che 1 minuto è abbastanza sicuro), in quanto l'alternativa è riscrivere il codice Qt e compilare la versione personalizzata.
questa domanda sembra essere davvero valida per me. Se trovi una soluzione, ti dispiacerebbe condividere con la comunità? Si prega di fornire anche uno snippet di codice, in modo che gli ingegneri della SO possano aiutarvi con facilità. – Whoami
Perché non implementare l'invio di un heartbeat per mantenere attiva la connessione? – dtech
Se il server supporta WebSockets, è possibile controllare http://doc.qt.io/qt-5/qtwebsockets-index.html per una connessione persistente tra il client e il server. –