增加数据包大小时 RTT 会降低

RTT decrease when increasing the packet size

我在尝试计算 UDP 客户端和服务器之间的 RTT(往返时间)时遇到了一个非常不直观的结果。当我使用 20 字节的数据包时,RTT 为 4.0 毫秒,但当我将数据包大小增加到 15000 字节时,RTT 为 2.8 毫秒。为什么会这样? RTT 不应该随着数据包大小的增加而增加吗?

这是 UDP 服务器的代码。我运行这是java RTTServer 8080.

public class RTTServer {
    final static int BUFSIZE = 1024, COUNT=100000;

    public static void main(String args[]) {
        long start=Integer.MAX_VALUE;
        byte[] bufferRecieve = new byte[BUFSIZE];          
        DatagramPacket recievePacket = new DatagramPacket(bufferRecieve, BUFSIZE);

        for (;;)
        try (DatagramSocket aSocket = new DatagramSocket(Integer.parseInt(args[0]));) {
            aSocket.receive(recievePacket);
            DatagramPacket sendPacket = new DatagramPacket(recievePacket.getData(), recievePacket.getLength(), recievePacket.getAddress(), recievePacket.getPort());
            aSocket.send(sendPacket);
        } catch (Exception e) {            
            System.out.println("Socket: " + e.getMessage());            
        } 
    }
}

这是 UDP 客户端的代码。我 运行 这个是 java RTTClient 192.168.1.20 8080 15000.

public class RTTClient {
    final static int BUFSIZE = 1024;
    final static int COUNT = 1000;

    public static void main(String args[]) throws UnknownHostException {
        InetAddress aHost = InetAddress.getByName(args[0]);            
        byte[] dataArray = args[2].getBytes();
        byte[] bufferReceive = new byte[BUFSIZE];
        DatagramPacket requestPacket = new DatagramPacket(
                dataArray, dataArray.length, aHost, Integer.parseInt(args[1]));

        DatagramPacket responsePacket = new DatagramPacket(bufferReceive,BUFSIZE);

        long rtts = 0;

        for (int i =0 ; i < COUNT; i++){
            try ( DatagramSocket aSocket = new DatagramSocket();) {

            long start = System.currentTimeMillis();    
            aSocket.send(requestPacket);
            aSocket.receive(responsePacket);
            System.out.println(i);
            rtts += System.currentTimeMillis() - start;
            } catch (Exception e) {
                System.out.println("Socket: " + e.getMessage());
            }
        }
        System.out.println("RTT = "+(double)rtts/(double)COUNT);     
    }
}

您要测量的是请求客户端 OS 发送 UDP 数据包的速度。您没有衡量服务器接收它们的速度......或者实际上,它是否正在接收它们。

我怀疑发生的情况是,当您在客户端增加数据包大小时,您实际上压倒了客户端 UDP 堆栈(在内核中)。 OS 正在丢弃大部分数据包(静默地),它可以比接受它们进行传输的速度更快。

您可以通过测量接收到的数据包数量来获得支持(或不支持)该理论的一些证据。

可能影响此的另一个问题是对于单个 IP 数据包而言太大的 UDP 消息将被拆分为多个数据包,然后重新组合。数据包丢失导致重组失败,导致 ICMP "Time Exceeded" 消息被发送到发送方。这可能会导致它做一些意想不到的事情...