Qt中使用QNetworkAccessManager的持久连接

时间:2015-04-20 10:41:50

标签: qt qnetworkaccessmanager qnetworkrequest

我尝试使用Qt维护客户端和远程服务器之间的持久连接。我的服务方面很好。我在Qt做客户端。在这里,我将使用QNetworkAccessManager来使用get方法(部分QNetworkRequest方法)来请求服务器。我将能够发送和接收请求。

但是在一段时间(大约2分钟)之后,客户端正在暗示服务器,通过自动发布请求来关闭连接。我认为QNetworkAccessManager正在为此连接设置超时。我想在两端之间保持持久的联系。

我的方法是否正确,如果没有,有人可以指导我走正确的道路吗?

2 个答案:

答案 0 :(得分:3)

这个问题很有意思,所以让我们做一些研究。我设置了一个具有大保持活动超时的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代码并编译自定义版本。

答案 1 :(得分:0)

我根据定义说,2分钟的超时连接符合持久性条件。我的意思是,如果它不持久,你必须在每个请求上重新连接。与其他一些软件相比,2分钟相当慷慨。但经过一段时间的不活动后,它最终会超时,这是一件不值得惊喜的好事。某些软件允许更改超时期限,但是从Pavel的调查中可以看出,在Qt的情况下,超时是硬编码的。

幸运的是,解决方案很简单,只需安装一个计时器,每1分钟左右发送一次心跳(只是一个虚拟请求,不要与#34;心跳网络&#34;混淆),以保持连接活跃。在使用连接之前,请取消激活计时器,完成连接后,重新启动计时器。