繁体   English   中英

检测 TCP/IP 数据包丢失

[英]detecting TCP/IP packet loss

我通过套接字代码进行 tcp 通信,例如:

public void openConnection() throws Exception
{
   socket = new Socket();
   InetAddress iNet = InetAddress.getByName("server");
   InetSocketAddress sock = new InetSocketAddress(iNet, Integer.parseInt(port));
   socket.connect(sock, 0);

   out = new PrintWriter(socket.getOutputStream(), true);
   in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}

并发送方法为:

synchronized void send(String message)
{
 try
 {
    out.println(message);
 }
 catch (Exception e)
 {
    throw new RuntimeException(this.getClass() + ": Error Sending Message: "
        + message, e);
 }
}

我从网页上读到,TCP/IP 不保证数据包的传递,它会重试,但如果网络太忙,数据包可能会被丢弃([链接])。 1

在系统之间传输数据时可能会丢弃数据包,主要有两个原因:

  • 网络利用率高并导致拥塞
  • 网络硬件或连接器故障

TCP 旨在能够在网络上丢弃数据包时做出反应。 当数据包成功传送到其目的地时,目的地系统将确认消息发送回源系统。 如果在某个时间间隔内未收到此确认,则可能是因为目标系统从未收到过该数据包,或者是因为包含该确认的数据包本身已丢失。 在任一情况下,如果源系统在给定时间内未收到确认,则源系统假定目标系统从未收到该消息并重新传输它。 不难看出,如果网络性能差,首先丢包,而这些重传报文增加的负载只会进一步增加网络的负载,意味着会丢失更多的包。 此行为可能会导致非常迅速地在网络上创建危急情况。

有什么办法可以检测到目的地是否成功接收到数据包,我不确定out.println(message); 将抛出任何异常,因为这是非阻塞调用。 它会将消息放入缓冲区并返回以让 TCP/IP 完成其工作。

有什么帮助吗?

TCP 旨在能够在网络上丢弃数据包时做出反应。

正如您的引述所说,TCP 旨在自动对您在本文中提到的事件做出反应。 因此,您在此级别无需执行任何操作,因为这将由您正在使用的 TCP 实现(例如在操作系统中)处理。

TCP 有一些特性可以为您完成一些工作,但是您对它们的局限性感到怀疑是正确的(许多人认为 TCP 是一种有保证的交付协议,没有上下文)。

在 Linux 内核邮件列表(“ Re: Client 收到 TCP 数据包但没有 ACK ”)上有一个有趣的讨论

在您的用例中,实际上,这意味着您应该将您的 TCP 连接视为一个数据流,在每个方向上(典型的错误是假设如果您从头开始发送 n 个字节,您将读取 n 个字节在另一端读取单个缓冲区),并处理可能的异常。

正确处理java.io.IOException s(特别是java.net中的子类)将涵盖您描述的级别的错误情况:如果您遇到错误,请制定重试策略(取决于应用程序及其用户打算做什么) . 也依赖超时(不要将套接字设置为永远阻塞)。

应用协议也可以设计成在接收命令或请求时发送它们自己的确认。

这是将职责分配给不同层的问题。 TCP 堆栈实现将处理您提到的丢包问题,并在无法自行修复时抛出错误/异常。 它的职责是与远程 TCP 堆栈进行通信。 由于在大多数情况下您希望您的应用程序与远程应用程序通信,因此需要额外的确认。 通常,需要设计应用程序协议来处理这些情况。 (在某些情况下,您可以向上移动多个层,具体取决于哪个实体负责处理请求/命令。)

TCP/IP 不会丢弃数据包。 TCP 实现内部的拥塞控制算法负责重传。 假设有稳定的数据流被发送,接收方将向发送方确认收到的序列号。 发送方可以使用确认来推断哪些数据包需要重新发送。 发送方保留数据包,直到它们被确认。

作为应用程序,除非 TCP 实现提供接收拥塞通知的机制,否则它所能做的最好的事情就是为事务完成的时间设置超时。 如果超时发生在事务完成之前,应用程序可以声明网络过于拥塞,应用程序无法成功。

编码你需要的东西。 如果您需要确认,请实施它们。 如果您希望发件人知道收件人收到了信息,请让收件人发送某种确认。

从应用程序的角度来看,TCP 提供了一个双向字节流。 您可以通过简单地指定传达您需要传达的信息的字节流来传达您想要的任何信息。

不要试图让 TCP 做任何其他事情。 不要试图“教 TCP”你的协议。

暂无
暂无

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

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