繁体   English   中英

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

[英]How to find out if a client connection is terminated within a TCP socket connection in a java server?

我正在使用 TCP sockets 上的阻塞读/写来实现多线程服务器,其中 InputStream 和 OutputStream 原语由适当的读/写器包装。

如果客户端断开连接,则InputStreamReader's read()方法返回-1 ,但如果客户端连接完好无损,它会无限期地等待。 我该如何克服呢?

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

  1. 从作者的角度来看,连接“丢失”意味着作者在写入/发送到套接字时出错( OutputStream.write(...) )。 For TCP this happens only due to receiving FIN or RST, or due to retransmission timeout (isn't available in Java to be managed) or due to OS has detected the connection is lost with TCP keepalive ( https://tldp.org/ HOWTO/TCP-Keepalive-HOWTO/overview.html )

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

TCP 重传超时 (RTO) 和 TCP keepalive 工作不太好:

  1. RTO: https://pracucci.com/linux-tcp-rto-min-max-and-tcp-retries2.html
  2. Keepalive 更糟糕: https://docs.microsoft.com/en-us/windows/win32/winsock/so-keepalive 默认情况下 Windows 在 2 小时后发送第一个 TCP Keepalive 数据包(。)。 Linux https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html上的相同问题

因此,如果您是服务器,我强烈建议您只使用强制设置 SO_TIMEOUT(或您自己的解锁读取等效项),或者在应用程序级别引入运行状况/可用性检查。 有两种典型的模式:ping-pong(达到超时后,服务器向客户端发送 ping 数据包并等待收到返回的 pong),心跳(客户端应在指定时间段内发送心跳 package时间)。 请注意,通常客户端会遇到相同的问题,您可能会决定支持双方的 ping-pong/heartbeat。

只是关于主题https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/的有趣帖子

您是否在套接字 object 上创建输入 stream?

ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

然后你可以检查套接字是否连接使用

socket.isClosed()

在你的循环之间?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM