这是一个有趣的问题,让我们做一些研究。我设置了一个带有长连接保持时间的nginx服务器,并编写了最简单的Qt应用程序:
QApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest r(QUrl("http://myserver/"));
manager.get(r);
return a.exec();
我使用以下命令(在Linux控制台中)来监视连接并检查是否存在问题:
watch -n 1 netstat -n -A inet
我快速查看了Qt源代码,并发现它使用QTcpSocket
,并在QHttpNetworkConnectionChannel :: close
中关闭它。因此,在进程暂停时,我打开了调试器控制台(在Qt Creator中点击Window → Views → Debugger log
),并添加了断点:
bp QAbstractSocket::close
注意:这适用于cdb(MS调试器),其他调试器需要其他命令。还有一点要注意:我使用带有调试信息的Qt,如果没有这些信息,这种方法可能行不通。
等待两分钟后,我获得了
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)
这个操作的类是
QNetworkAccessCache
。它设置定时器,确保在
QNetworkAccessCache::Node::timestamp
过期时删除其对象。这些对象包括HTTP连接、FTP连接和凭据。
接下来,什么是
timestamp
?在释放对象时,其时间戳是按以下方式计算的:
node->timestamp = QDateTime::currentDateTime().addSecs(ExpiryTime)
而且ExpiryTime = 120
是硬编码的。
所有涉及的类都是私有的,我找不到任何阻止这种情况发生的方法。因此,每分钟发送保持活动请求(至少现在您知道1分钟足够安全)要简单得多,因为另一种选择是重新编写Qt代码并编译自定义版本。