【问题标题】:Handling socket disconnection. Boost / Winsock处理套接字断开连接。升压/Winsock
【发布时间】:2013-05-28 21:39:19
【问题描述】:

正如标题所暗示的,我使用过winsock 和boost 插座。我在检测断开连接时遇到了难以置信的困难。

首先,我知道可以通过以下方式发现断线:

  1. recv() / async_read() 返回套接字错误或 0。
  2. send() / async_write() ... ... ...
  3. 客户端是否手动关闭、被中断/程序关闭 - 随便。

所以这里是问题场景:

我用 closesocket() 关闭了我的连接。客户端检测到断开连接 - 一切正常。

我关闭了程序 - 客户端有 50/50 的机会无法检测到断开连接。由于某种原因,我的重叠 IO WSARecv() 不能保证检测到。

我终止进程。检测的机会增加到 80%。 But for the rest of the 20% - here's what's bothering me. I implemented a keep-alive ping mechanism which sends data to the server. Even if I killed the program - the server is still async_writing() to the connection - even though it's not detected or dead.

这是我必须忍受的吗?我有点迷失了,因为我尽我所能检测断线……但它们仍然是个问题。

【问题讨论】:

  • 你在 TCP 上实现了什么协议?它有协议规范吗?
  • 当连接被异常终止/丢失时,操作系统无法知道它已经消失了一段时间,因此在此期间它不会报告错误,并缓冲输出数据等待让对等方接受数据。这就是socket-level keepalives和protocol-level pings发挥作用的地方。如果 keepalive/ping 超时并且无法及时响应,则无论其实际状态如何,都只需关闭套接字。

标签: c++ sockets networking boost disconnection


【解决方案1】:

TCP 不保证仅接收的一方可以检测到连接丢失。您在 TCP 之上实现的协议应该在其设计中考虑到这一点。如果没有,协议就被破坏了,你应该向设计它的人大声抱怨。

如果您自己设计协议,请不要跳过记录协议的步骤。这应该始终包括它是否支持应用程序级消息、它们是如何构建的、谁在何时传输、如何检测到断开连接、任何超时等等。在没有实际设计的情况下实施的“即兴”协议基本上注定要失败,即使它碰巧工作,也永远无法维护,因为实际上不可能确定它应该如何工作。

一旦您有了协议规范,至少可以通过以下简单步骤确定问题所在:

  1. 服务器是否遵循规范?如果没有,请停止。服务器坏了。

  2. 客户是否遵循规范?如果没有,请停止。客户端坏了。

  3. 停止。规范被破坏了。

没有规范,这些问题是无法回答的。很多痛苦就是这样造成的。

【讨论】:

    猜你喜欢
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多