如何确定客户端连接是否在java服务器的TCP套接字连接中终止?

如何确定客户端连接是否在java服务器的TCP套接字连接中终止?,java,multithreading,sockets,server,tcp,Java,Multithreading,Sockets,Server,Tcp,我正在实现一个多线程服务器,使用由适当的读写器包装的InputStream和OutputStream原语在TCP套接字上阻塞读写 如果客户端断开连接,则InputStreamReader的read()方法返回-1,但如果客户端连接完好,则该方法将无限期地等待。如何克服这个问题?您是否正在通过套接字对象创建输入流 ServerSocket server = new ServerSocket(port); Socket socket = server.accept(); DataInputStrea

我正在实现一个多线程服务器,使用由适当的读写器包装的InputStream和OutputStream原语在TCP套接字上阻塞读写


如果客户端断开连接,则
InputStreamReader的read()
方法返回
-1
,但如果客户端连接完好,则该方法将无限期地等待。如何克服这个问题?

您是否正在通过套接字对象创建输入流

ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
然后,您可以使用检查插座是否已连接

socket.isClosed()

在循环之间?

这里最重要的问题是“丢失”对应用程序真正意味着什么。套接字通信中有两个角色-编写器和读取器。我们的代码可能同时扮演这两个角色。因此,对于套接字通信:

  • 从编写器的角度来看,连接“丢失”意味着编写器在向套接字写入/发送时出错(
    OutputStream.write(…)
    )。对于TCP,这仅是由于接收FIN或RST,或由于重新传输超时(在Java中不可管理),或由于操作系统检测到TCP keepalive()的连接丢失而发生的

  • 从读卡器的角度来看,连接“丢失”意味着读卡器在从套接字读取时出错(
    InputStream.read(…)
    )。对于TCP,这仅是由于接收FIN或RST,或由于操作系统检测到与TCP keepalive的“丢失”连接,或由于阻塞读取超时(SO_超时)而发生的

  • TCP重传超时(RTO)和TCP保持工作不太好:

  • RTO:
  • Keepalive甚至是最糟糕的:。默认情况下,Windows在2小时后发送第一个TCP Keepalive数据包(!)。Linux上也存在同样的问题
  • 因此,如果您是一个服务器,我强烈建议您只使用强制设置So_超时(或您自己的用于取消阻止读取的等效项),或者在应用程序级别引入运行状况/可用性检查。有两种典型模式:乒乓(在达到超时后,服务器向客户端发送一个乒乓数据包,并等待收到回乒乓)、心跳(客户端应在指定的时间段内发送心跳数据包)。请注意,客户机经常遇到相同的问题,您可能会决定为双方支持乒乓球/心跳


    关于“TCP套接字连接中的客户端连接丢失”这一主题的有趣帖子毫无意义。不清楚您在问什么,除非您正在寻找的是套接字读取超时。抱歉误解。在我的例子中,客户端有一个超时,在此超时之后操作终止。ruby客户端在这个函数调用周围有一个Timeout::Timeout。那么你的问题是什么?timout跳闸->出了问题。可能是网络或慢速服务器或其他一些东西,但这是您唯一可用的机制。NB“连接在TCP连接内终止”也没有意义。您似乎将神奇的特性归因于
    isClosed()
    。它不像你想象的那样。它最初是错误的,当你关闭套接字时变为真,而不是在其他任何时候:特别是,当对等方断开连接或连接中止时,它不会神奇地变为真。如果你想替换
    isConnected()
    ,出于同源原因,这也不起作用。您还没有尝试过这个。