Qt:当用户关闭时,在控制台应用程序中检测QTcpSocket断开连接

时间:2017-11-08 05:43:52

标签: qt qtcpsocket

我的问题标题应该足够了。我已经尝试过(没有成功):

  1. 在函数中使用C风格的析构函数:__attribute__((destructor))
    void sendToServerAtExit() __attribute__((destructor)) { mySocket->write("$%BYE_CODE%$"); }
  2. 调用应用程序析构函数,但套接字已断开连接,我无法写入服务器。

    1. 使用标准C函数atexit(),但TCP连接已丢失,因此我无法向服务器发送任何内容。
      atexit(sendToServerAtExit); // is the same function of point 1
    2. 我找到的解决方案是每秒检查所有连接的套接字是否仍然连接,但我不想这样做效率低下。它只是一个临时解决方案。此外,我希望其他应用程序(甚至是网络应用程序)可以加入我的控制台应用程序的聊天室,而且我不想每秒都要求数据。

      我该怎么办?

3 个答案:

答案 0 :(得分:2)

处理以下信号(QTcpSocket继承自QAbstractSocket

void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)

在调用的广告位中,检查socketState是否为QAbstractSocket::ClosingState

QAbstractSocket::ClosingState表示套接字即将关闭。

http://doc.qt.io/qt-5/qabstractsocket.html#SocketState-enum

答案 1 :(得分:1)

您可以将插槽连接到断开信号。

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()

答案 2 :(得分:0)

如果我理解你的问题是正确的,你想通过TCP发送数据,以通知远程计算机你正在关闭套接字。

从技术上讲,这可以通过听取QIODevice::aboutToClose()QAbstractSocket::stateChanged()信号在Qt中完成。

但是,如果您慷慨地退出程序并通过向远程计算机发送QTcpSocket数据包来关闭FIN。这意味着在远程计算机上 将通知正在运行的程序TCP连接已完成。例如,如果远程程序也使用QTcpSocketQAbstractSocket::disconnected() 信号将被发出。

当其中一个程序没有慷慨地退出(崩溃,硬件问题,电缆拔掉等)时,会出现真正的问题。在这种情况下,TCP FIN数据包将 不发送,远程计算机永远不会收到TCP连接另一端断开连接的通知。 TCP连接将在几分钟后超时。 但是,在这种情况下,您无法将最后一段数据发送到服务器。

最后,唯一的解决方案是不时地发送“我在这里”数据包。尽管你声称它是无效的,但它是一种广泛使用的技术,它还具有工作原理的优势。