繁体   English   中英

如何在 Java 应用程序中检测 FIN - tcp 标志?

[英]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 并从套接字读取:

  • 在对等方关闭连接的情况下,读取操作将返回“-1”
  • 在读取超时的情况下,读取操作将抛出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.

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