Java套接字不会在死锁套接字上抛出异常?
我们的移动设备和我们的服务器都采用Java编写的简单的客户端服务器架构。 一个非常简单的ServerSocket和Socket实现。 然而,一个问题是,当客户端突然终止(没有正确关闭套接字)时,服务器不知道它已断开连接。 此外,服务器可以继续写入此套接字而不会发生任何异常。 为什么?
根据文档,如果您尝试写入另一端无法访问的套接字,则Java套接字应该会引发异常!
该连接最终将通过重新发送超时(RTO)超时。 但是,使用基于网络延迟(RTT)的复杂算法计算RTO,请参阅此RFC,
http://www.ietf.org/rfc/rfc2988.txt
所以在移动网络上,这可能需要几分钟。 等待10分钟,看看是否可以超时。
解决这类问题的方法是在自己的应用程序协议中添加一个心跳,并在没有获取心跳ACK时断开连接。
这里的关键词(without closing the socket properly)
。
套接字应该总是以这种方式获取和处置:
final Socket socket = ...; // connect code
try
{
use( socket ); // use socket
}
finally
{
socket.close( ); // dispose
}
即使采取这种预防措施,您也应指定特定于协议的应用程序超时。
我的经验表明,不幸的是,你不能可靠地使用任何Socket超时功能(例如,写操作没有超时,甚至读操作有时可能永远挂起)。
这就是为什么你需要一个看门狗线程来强制你的应用程序超时并处理一段时间没有响应的套接字。
一种便捷的方法是通过java.nio中的相应通道初始化Socket和ServerSocket。 这种套接字的主要优点是它们是可中断的,这样你就可以简单地中断执行套接字协议的线程,并确保套接字被正确处理掉。
请注意,您应该在双方执行应用程序超时,因为只有时间问题和运气不佳时才会遇到无法响应的套接字。
TCP / IP通信可能非常奇怪。 TCP将在堆栈的底层重试相当长的一段时间,而不会让上层知道发生了什么事情。
我完全认为经过一段时间(30秒到几分钟)后,你应该会看到一个错误,但我没有测试过,我只是想说TCP应用程序是如何工作的。
你可能能够收紧TCP规格(重试,超时等),但又一次,没有太多搞砸了。
另外,这可能是我完全错了,你使用的Java的实现只是片状。
链接地址: http://www.djcxy.com/p/1657.html