我正在尝试确定客户端是否已从netty关闭套接字连接。有没有办法做到这一点?
答案 0 :(得分:21)
在通常情况下,客户端通过close()
关闭套接字并且TCP关闭握手已成功完成,将触发channelInactive()
(或channelClosed()
in 3)事件。
但是,在一个不寻常的情况下,例如客户端计算机由于停电或拔下LAN电缆而脱机,可能需要很长时间才能发现连接实际已关闭。要检测这种情况,您必须定期向客户端发送一些消息,并期望在一定时间内收到响应。它就像一个ping - 您应该在协议中定义一个定期的ping和pong消息,除了检查连接的健康状况之外几乎什么都不做。
或者,您可以启用SO_KEEPALIVE
,但此选项的keepalive间隔通常取决于操作系统,我不建议使用它。
为了帮助用户相对轻松地实现此类行为,Netty提供了ReadTimeoutHandler
。配置管道,以便ReadTimeoutHandler
在一段时间内没有入站流量时引发异常,并在exceptionCaught()
处理程序方法中关闭异常连接。如果您是应该发送定期ping消息的一方,请使用计时器(或IdleStateHandler
)发送它。
答案 1 :(得分:0)
这取决于您在netty上使用的协议。如果您将其设计为支持类似ping的消息,则只需发送这些消息即可。除此之外,netty只是TCP的一个非常薄的包装。
另请参阅描述isOpen()
及相关内容的this SO post。然而,这并没有解决保持活动的问题。
答案 2 :(得分:0)
如果您正在编写服务器,并且netty是您的客户端,那么您的服务器可以通过调用select()
或等效项来检测断开连接,以检测套接字何时可读,然后调用recv()
。如果recv()
返回0,则客户端正常关闭套接字。如果recv()
返回-1,则检查errno
或等效实际错误(除少数例外情况,大多数错误应视为非正常断开)。关于意外断开连接的事情是它们可能需要很长时间才能检测到操作系统,因此您必须启用TCP保持活动,或者要求客户端定期向服务器发送数据。如果在一段时间内没有从客户端收到任何信息,那么只需假设客户端已经离开并关闭您的连接结束。如果客户想要,则可以重新连接。
答案 3 :(得分:0)
如果您从对等方已关闭的连接中读取,您将获得某种类型的流末尾指示,具体取决于API。如果您写入此类连接,您将收到IOException:'connection reset'。 TCP没有提供任何其他方法来检测已关闭的连接。
默认情况下,TCP keep-alive(a)处于关闭状态,(b)默认情况下,默认情况下每两小时运行一次。这可能不是你想要的。如果您使用它并在检测到连接断开后进行读取或写入,则会出现上面的重置错误,