![](/img/trans.png)
[英]How can a Java application be informed on receipt of a [FIN,ACK] on a TCP connection?
[英]How to detect FIN - tcp flag in java application?
我在两台计算机之间建立了持久的 TCP 连接(第二个不在我的控制之下)。 第二台计算机可以随时发送 FIN 标志,首先必须关闭连接(将 FIN 标志发送回第二台计算机)。
我怎么知道第二台计算机发送了一个 FIN 标志,以及何时必须引起 Java 应用程序的 socket.close() 方法?
通常,您必须读取连接,当 EOF 或适当的 IOException 返回 -1 时,您可以关闭连接。 注意: SocketTimeoutException 并不意味着连接已关闭。
一个例子。
boolean ok = false;
try {
int b = in.read();
ok = b >= 0;
if (!ok)
throw new EOFException();
} finally {
if (!ok)
in.close();
}
如上所述,Socket 的属性(isClosed、isConnected 等)没有帮助。 正确的解决方案是设置合理的 SO_TIMEOUT 并从套接字读取:
SocketTimeoutException
。(斯卡拉代码)
val socket = new Socket("localhost", 8888)
socket.setSoTimeout(10000) /* Set reasonable read timeout */
try {
val res = socket.getInputStream().read()
if (res < 0)
... /* Socket closed */
else
... /* Socket read succeeded */
} catch {
case _: SocketTimeoutException => ... /* Socket not closed */
case _ => ... /* Merde */
}
使用旧的 Java I/O 库只能部分检测到对方关闭的软连接(当他们设法发送 FIN/RST 标志时)。 您只能通过超时了解到连接断开,因此可能远非立即发生。 在他们意识到另一端的派对早已不复存在之前,您的线程可能会挂起很长时间。
为了更好地处理它,您需要使用nio
。 在那里, Selector
会识别出这种情况,说有数据可供读取,但随后在返回小于零的通道上读取。 这将使您几乎立即了解软连接重置。
另一方面,无论您使用哪个库,硬连接终止(例如有人切断线路或网络中断)只能通过超时检测,因为它是 TCP 协议本身的属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.