【问题标题】:Java TCP re-tranmission timeoutJava TCP 重传超时
【发布时间】:2013-07-14 06:59:30
【问题描述】:
public static void main(String args[]){

    byte[] message = ...
    Socket socket = ...
    DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());

    dOut.write(message);  //#1

    dOut.close();
    socket.close();
}

假设第 1 行将数据放入缓冲区等待刷新到远程机器。之后,流和套接字关闭。

我们假设,在发送过程中,网络发生了一些未知的问题,我们的操作系统会重新发送缓冲区中的数据包,直到 TCP 重传超时。

我想知道如何在 Java 程序中捕获此异常?因为上面的代码已经将数据发送到缓冲区,并且可能关闭了流和套接字(并且可能退出了 Java 主体),所以将所有其他工作(TCP 相关,重新传输)留给了操作系统。

我的问题是,即使 Java 程序退出,TCP 重新传输(我们假设数据包丢失)会继续吗?捕获重传超时错误的最佳方法是什么?

【问题讨论】:

  • 不存在“Java TCP 重新传输超时”或“Java TCP”之类的东西。只有平台的 TCP 堆栈及其行为。
  • 嗨@EJP,我知道 dOut.write 只有在 TCP 发送缓冲区已满时才会被阻止。假设dOut.write由于缓冲区已满而被阻塞,并且网络发送数据有问题,因此TCP继续重新发送数据。这种情况下,dOut.write会在TCP超过最大重传时间后抛出异常吗?感谢您的帮助。

标签: java sockets tcp operating-system


【解决方案1】:

即使在程序退出后,TCP 也会继续尝试干净地关闭连接。通常建议应用程序自行执行关机。基本上,您执行以下一系列步骤:

  1. Shutdown the TCP connection in the send direction 触发正常关闭序列。如果协议禁止对方发送任何数据,您也可以关闭接收方向的连接,但是,如果您这样做并且对方发送任何数据,可能会导致对方检测到异常关闭,因为它发送的数据将会丢失。

  2. 继续从连接中读取,直到从另一端检测到干净或异常关闭。如果一切顺利,您将在收到对方发送的任何数据后立即检测到干净关机。

  3. 关闭句柄或删除连接的对象/引用。实际的 TCP 连接已经关闭。

【讨论】:

  • 嗨,我不完全理解第一行“即使在程序退出后,TCP 也会继续尝试干净地关闭连接”。是不是说,即使Java程序已经退出,操作系统也会继续发送(直到远程机器接收到数据或超时)?
  • @GMsoF:这取决于实施。可能是操作系统。它可能是不属于操作系统的单独 TCP 堆栈。它可能是JVM。但这是最常见的做法。为安全起见,应用程序应管理关闭以确保获得所需的行为。
  • JVM退出后不能是JVM。
  • @EJP:JVM 可以退出是一个实现细节。 JVM 可以在硬件中实现。实现细节真的没那么有趣。
猜你喜欢
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
相关资源
最近更新 更多