Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接
Posted
技术标签:
【中文标题】Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接【英文标题】:Qt: Detect a QTcpSocket disconnection in a console app when the user closes it 【发布时间】:2017-11-08 05:43:51 【问题描述】:我的问题标题应该足够了。我已经尝试过(没有成功):
-
在函数中使用 C 风格的析构函数:
__attribute__((destructor))
:void sendToServerAtExit() __attribute__((destructor))
mySocket->write("$%BYE_CODE%$");
调用了应用析构函数,但是socket已经断开,无法写入服务器。
-
使用标准C函数
atexit()
,但是TCP连接已经丢失,所以我无法向服务器发送任何内容。atexit(sendToServerAtExit); // is the same function of point 1
我找到的解决方案是每秒检查所有连接的套接字是否仍然连接,但我不想这样做效率低下的事情。这只是一个临时解决方案。另外,我希望其他应用程序(甚至是网络应用程序)可以加入我的控制台应用程序的聊天室,并且我不想每秒都请求数据。
我该怎么办?
【问题讨论】:
显示你的代码。 【参考方案1】:处理下面的信号(QTcpSocket
继承自QAbstractSocket
)
void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
在调用的槽内,检查socketState
是否为QAbstractSocket::ClosingState
。
QAbstractSocket::ClosingState
表示套接字即将关闭。
http://doc.qt.io/qt-5/qabstractsocket.html#SocketState-enum
【讨论】:
或者aboutToClose()
信号在这种情况下更直接。【参考方案2】:
您可以将插槽连接到断开信号。
connect(m_socket, &QTcpSocket::disconnected, this, &Class::clientDisconnected);
检查documentation。
您还可以使用这样的插槽知道哪个用户已断开连接:
void Class::clientDisconnected
QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());
if(client)
// Do something
client->deleteLater();
else
// Handle error
如果您有连接池,此方法很有用。如果你只有一个连接,你也可以使用它,但不要忘记nullptr
在client->deleteLater()
之后。
【讨论】:
问题是关于在套接字关闭之前发送数据。disconnected()
信号被延迟发出。
那么你应该从你的客户端实现一个预断开机制。即使是“即将断开”的 qtcpsocket 状态也是无效的,因为客户端不会监听新的传入字节。【参考方案3】:
如果我正确理解您的问题,您希望通过 TCP 发送数据以通知远程计算机您正在关闭套接字。
从技术上讲,这可以在 Qt 中通过监听 QIODevice::aboutToClose()
或 QAbstractSocket::stateChanged()
信号来完成。
但是,如果您慷慨地退出程序并通过向远程计算机发送FIN
数据包来关闭QTcpSocket
。这意味着在远程计算机上,
正在运行的程序将被通知 TCP 连接已完成。例如,如果远程程序也使用QTcpSocket
,则QAbstractSocket::disconnected()
将发出信号。
真正的问题出现在其中一个程序没有正常退出时(崩溃、硬件问题、电缆拔出等)。在这种情况下,TCP FIN
数据包将
不会发送,远程计算机将永远不会收到 TCP 连接的另一端已断开连接的通知。 TCP 连接将在几分钟后超时。
但是,在这种情况下,您也无法将最终数据发送到服务器。
最后,唯一的解决方案是不时发送“我在这里”数据包。尽管您声称它效率低下,但它是一种广泛使用的技术,并且它还具有有效的优势。
【讨论】:
以上是关于Qt:当用户关闭它时,在控制台应用程序中检测到 QTcpSocket 断开连接的主要内容,如果未能解决你的问题,请参考以下文章
Android:检测 GPS 何时打开/关闭(或当没有应用程序不再使用它时)
Qt 对于我的带宽上限来说太大了。我的替代方案是啥? [关闭]