【问题标题】:Best way to handle client disconnection using TCP socket使用 TCP 套接字处理客户端断开连接的最佳方法
【发布时间】:2014-01-22 15:30:18
【问题描述】:

我设法创建了基本的远程管理员工具,它工作正常,我在 c++ 中使用基本的 tcp 套接字和多线程。就像 90% 完成了一些我可以用来远程使用它的功能,但是我的软件没有任何东西可以检测客户端断开连接,除非客户端手动关闭,客户端将向服务器发送断开连接消息,但是当当用户拔出网络或其他东西时会发生断开连接,最好的处理方法是什么,我正在寻找一种专业的方法来处理它,例如如果客户端断开连接,服务器会立即检测到哪个客户端断开连接。

【问题讨论】:

    标签: c++ tcp


    【解决方案1】:

    空闲 TCP 连接不必发送任何数据来保持连接。您尝试检测的场景称为“半开”连接。 Stevens 书中第 7.5 章(我的第 186 页)中有一张选项图表。最终结果是这样的:

    1. 如果您正在主动发送数据,则连接将超时等待来自远程系统的确认(超时取决于系统,但通常在分钟范围内)。
    2. 如果您启用了 keep-alives(并且它们得到了适当的支持),系统将在 2 小时 不活动后超时。远程系统无响应将导致超时
    3. 如果您没有启用 keep-alives 并且没有发送数据,则无法检测到丢失的客户端。

    这意味着,如果您想在断开连接时相对快速地关闭连接,您需要添加自己的方式。我通常会强迫一方发送某种心跳。

    【讨论】:

    • 好吧,维基百科说不是:en.wikipedia.org/wiki/TCP_half-open 史蒂文斯似乎同意:“但如果客户端主机崩溃,服务器进程将永远不会知道它,服务器将不断等待输入永远不会到达。这称为*半开连接。"
    • 请见谅。我发现几十年来我一直在错误地使用这个词。
    【解决方案2】:

    就像@EJP 说的那样,没有办法立即检测到硬断开连接,因为本地计算机无法看到网络上发生的事情,它只能看到其传出的 TCP 数据包没有被确认了。它无法知道缺少 ACK 是由于临时问题(如过载的路由器丢弃了一些数据包,或者以太网电缆被拔出然后快速重新插入)还是更永久的问题(如远程计算机崩溃、永久断电或与网络断开连接)。

    您可以做的是确保您的本地应用程序始终通过 TCP 套接字定期发送数据——无论是实际数据,或者如果您没有任何实际数据要发送,请发送一些客户端将发送的虚拟字节知道忽略。这些“心跳消息”可以每分钟发送一次,也可以每隔几秒发送一次,具体取决于您愿意为此目的使用多少额外带宽。

    定期发送 TCP 数据的作用是强制本地计算机的 TCP 堆栈监视与发送的数据包对应的 ACK;如果它没有收到预期的ACK,它将重新发送数据包,并且在几轮重新发送后,它将放弃并关闭TCP连接。大多数 TCP 堆栈会在几分钟未收到 ACK 后放弃。

    如果“几分钟”对您来说不够快,您可能需要远程程序每隔几秒钟向您的程序发送某种数据,如果您还没有,则强制关闭 TCP 套接字从客户端收到任何数据至少(这么多秒)。请注意,根据您设置为超时的秒数,这可能会导致“误报”,您的程序会强制关闭实际上仍然可行但暂时陷入困境的 TCP 连接;您的应用程序可能接受也可能不接受。

    【讨论】:

      【解决方案3】:

      除非客户端正确关闭连接,否则您无法立即检测到它。您必须使用读取超时,并对 send() 或 recv() 返回的所有其他错误做出正确反应,即关闭套接字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        • 1970-01-01
        • 1970-01-01
        • 2021-03-25
        • 1970-01-01
        • 2010-12-20
        相关资源
        最近更新 更多