【问题标题】:TCP keep-alive to determine if client disconnected in nettyTCP keep-alive判断客户端是否在netty中断开连接
【发布时间】:2014-02-16 23:44:48
【问题描述】:

我正在尝试确定客户端是否关闭了来自 netty 的套接字连接。有没有办法做到这一点?

【问题讨论】:

    标签: tcp netty


    【解决方案1】:

    这取决于您在 netty 上使用的协议。如果您将其设计为支持类似 ping 的消息,则可以简单地发送这些消息。除此之外,netty 只是 TCP 的一个非常薄的包装器。

    另见this SO post,其中描述了isOpen() 及相关内容。然而,这并不能解决保活问题。

    【讨论】:

    • 该链接中的答案大多不正确。 SO中有更好的答案。
    • @EJP 你有链接吗?如果您可以提出修改建议,我将很乐意接受!
    • 我的理解是tcp内置了keep-alive。难道不能利用这个吗?
    • 是的。 TCP keep-alive默认是关闭的,建立连接后开启即可。
    • 我建议你链接到this answer
    【解决方案2】:

    如果您正在编写服务器,而 netty 是您的客户端,那么您的服务器可以通过调用 select() 或等效的方法检测套接字何时可读,然后调用 recv() 来检测断开连接。如果recv() 返回 0,则客户端优雅地关闭了套接字。如果recv() 返回-1,则检查errno 或等效的实际错误(除了少数例外,大多数错误应被视为不正常的断开连接)。意外断开连接的问题是操作系统可能需要很长时间才能检测到,因此您必须启用 TCP 保持连接,或者要求客户端定期向服务器发送数据。如果在一段时间内没有从客户端收到任何内容,那么只需假设客户端已消失并关闭您的连接端。如果客户端愿意,它可以重新连接。

    【讨论】:

    • 我认为您误读了这个问题。他似乎在服务器中使用 Netty。
    【解决方案3】:

    如果您从已被对等方关闭的连接中读取,您将获得某种类型的流结束指示,具体取决于 API。如果你写入这样的连接,你会得到一个 IOException: 'connection reset'。 TCP 不提供任何其他检测关闭连接的方法。

    TCP keep-alive (a) 默认关闭,(b) 默认情况下每两小时运行一次。这可能不是你想要的。如果你使用它并在它检测到连接断开后进行读取或写入,你会得到上面的重置错误,

    【讨论】:

    • 在 Windows 2000 及更高版本上,您可以使用 WSAIoctl(SIO_KEEPALIVE_VALS) 以编程方式在每个连接的基础上设置所需的 TCP keep-alive 间隔。
    【解决方案4】:

    在客户端通过close()关闭套接字并且TCP关闭握手已成功完成的通常情况下,将触发channelInactive()(或3中的channelClosed())事件。

    但是,在不寻常的情况下,例如客户端计算机由于断电或拔出 LAN 电缆而脱机,您可能需要很长时间才能发现连接实际上已断开。要检测这种情况,您必须定期向客户端发送一些消息,并期望在一定时间内收到其响应。这就像一个 ping - 您应该在您的协议中定义一个周期性的 ping 和 pong 消息,它实际上除了检查连接的健康状况之外什么都不做。

    或者,您可以启用SO_KEEPALIVE,但此选项的保活间隔通常取决于操作系统,我不建议使用它。

    为了帮助用户相对容易地实现这种行为,Netty 提供了ReadTimeoutHandler。配置您的管道,以便ReadTimeoutHandler 在一段时间内没有入站流量时引发异常,并在您的exceptionCaught() 处理程序方法中关闭异常连接。如果您是应该发送周期性 ping 消息的一方,请使用计时器(或 IdleStateHandler)发送它。

    【讨论】:

      猜你喜欢
      • 2013-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多