在Java中如何处理Socket断开连接?

13

大家好。我有一个使用ServerSocket和Socket类编写的Java服务器。

我希望能够检测和处理断开连接,必要时重新连接新客户端。

如何正确地检测客户端断开连接、关闭套接字并接受新客户端?

3个回答

12

假设你正在从套接字中读取数据,可能是通过输入流的包装类,如BufferedReader。在这种情况下,当相应的read操作返回-1(对于原始的read()调用)或null(对于readLine()调用)时,您可以检测到流的末尾。

当尝试在已关闭的套接字上执行某些操作时,会引发SocketException异常,您也需要适当处理该异常。


1
当说到“关闭的套接字”时,意思是关闭了套接字,而不是对等方关闭了连接。除了所提到的方法之外,所有的readXXX()方法在遇到EOS时都会抛出EOFException异常。 - user207421

4

检测另一端是否离线的唯一安全方式是定期发送心跳,并使另一端基于缺少心跳而超时。


或者你可以直接设置超时时间。 - Pyrolistical
2
我有一个线程,它检查每个连接,以查看自上次读取数据包以来的时间(心跳或其他)。 如果时间太长,我会关闭该连接。 - Peter Lawrey
@PeterLawrey,发送心跳是大多数电信系统使用的最佳解决方案之一。心跳可以用来响应断开连接。 - Alpesh Gediya
@AlpeshGediya 我把所有的消息都视为心跳。这意味着只有在一段时间内没有发送任何消息时才需要发送心跳。在高负载下,我发现这种方法容易出错。例如,如果你读取了很多密集的消息,导致心跳花费了很长时间才被读取,那么你就不希望超时了一个心跳。 - Peter Lawrey
@PeterLawrey,是的,在高流量交通下,该解决方案面对现实... :) - Alpesh Gediya

-1

是我一个人发现了吗?还是没有人注意到JavaDoc中有一个ServerSocket api下的方法,它允许我们根据服务器套接字的关闭状态获取布尔值?

你可以每隔几秒钟循环一次来检查它的状态:

if(!serverSocket.isClosed()){
  // whatever you want to do if the serverSocket is connected
}else{
  // treat a disconnected serverSocket
}

编辑:再次阅读您的问题,似乎您需要服务器不断搜索连接,如果客户端断开连接,则应能够重新检测到客户端尝试重新连接。这不应该是您的第一选择吗?

拥有一个正在侦听的服务器,一旦它接收到客户端连接,它应该将其传递给工作线程对象并启动它以异步操作。然后服务器可以回到循环以侦听新的连接。如果客户端断开连接,则启动的线程应该终止,当它重新连接时,将再次启动新线程来处理新的连接。

Jenkov提供了这种实现的很好的示例。


4
isClosed()并不能告诉你对等方是否已断开连接。它只能告诉你是否已关闭你的套接字 - user207421
1
ServerSocket.isClosed() 只告诉您是否已关闭 serversocket。它与任何类型的客户端完全无关。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接