为什么IP、TCP、UDP数据包的最大长度不合适?

网络工程 ip 以太网 通讯协议 UDP
2021-07-12 21:33:28

从许多教程中,我得到了以下知识(也许我被误解了):

  • 一个以太网数据包的最大长度约为 1500 字节。

  • IP 数据包的最大长度约为 65535 字节。

  • UDP 数据包的最大长度为 65515 字节

但是当我进行测试并观看 Wireshark 时,我得到了不同的答案。

  1. 我尝试使用 TCP 协议发送一些大数据。

    Socket con = new Socket("localhost", 8088);
    OutputStream os = con.getOutputStream();

    StringBuilder s = new StringBuilder();
    for( int i = 0; i < 10000; i++) {
      s.append("Hello world");
    }
    // about 110k bytes
    byte[] data = s.toString().getBytes();

    os.write(data);
    os.close();
    con.close();

这是我的 Java 代码(没有必要理解这一点。),我尝试使用 TCP 连接发送 110k 字节的数据。这是我的 Wireshark。

在此处输入图片说明

我的 110k 字节消息被拆分为 7 个数据包,我认为这表明 TCP 数据包的最大长度为 16388 字节。

  1. 然后,我尝试发送一个 UDP 数据包:
    DatagramSocket client = new DatagramSocket(50555);

    StringBuilder s = new StringBuilder();
    for( int i = 0; i < 10000; i++) {
      s.append("Hello world");
    }
    // 110k bytes
    byte[] data = s.toString().getBytes();

    int messageLength = data.length;
    for (; ; messageLength--){
      try{
        DatagramPacket packet = new DatagramPacket(data, messageLength, 
          new InetSocketAddress("localhost", 8088));
        // If packet is still too lang, above line will throws an exception

        // If there is not any exception, means we can send this packet
        // and this messageLength is the limit value for a UDP packet.
        client.send(packet);
        System.out.println("message length is " + messageLength);

        // break for loop
        break;
      } catch(Exception e){
        // fail to send and continue for loop
      }
    }
    client.close();

结果是message length is 65507

我真的很困惑:

  • IP协议建立在以太网或其他东西上,当以太网只能发送1500字节时,为什么IP数据包可以是65535字节?

  • 为什么一个 TCP 数据包只有 16388 字节?

然后我在 SOF 或其他网站上阅读了很多帖子,但我没有得到答案,我认为不会与其他人重复。

2个回答

IP协议建立在以太网或其他东西上,当以太网只能发送1500字节时,为什么IP数据包可以是65535字节?

以太网是可用于传输 IP(以及 IP 之外的协议)的几个物理层之一。物理层可以传输的数据包大小是特定于该物理层的,其他物理层具有其他属性。请注意,在您在 localhost (127.0.0.1) 上进行通信的特定情况下,根本不涉及物理层(因此也没有以太网),因为 localhost 只是一个逻辑而不是物理网络接口。

IP 中的 65535 字节限制是因为IP 头中的长度字段只有 16 位。

为什么一个 TCP 数据包只有 16388 字节?

应用程序将数据发送到操作系统内核,然后操作系统内核将数据打包。可以一次发送到内核的数据大小取决于套接字缓冲区的大小,这会导致您看到的数据包大小。此外,内核可能会进一步拆分数据以最适合底层物理层(如以太网)的最大大小。使用 TCP,内核也可能决定加入小数据,以便它们一起传输。

请注意,对于 TCP,线路上的数据包长度实际上与应用程序无关,因为 TCP 是连续数据流。对于 UDP,这将是不同的,即每个send都会导致单个 IP 消息,并且也将作为这样的单个消息被接收者接收。

不同的数据链路协议是由不同的人在不同的时间设计的,它们都有自己的 MTU(最大有效载荷大小)。以太网是 Bob Metcalfe 的大学论文,它设计有 1500 个八位字节的 MTU。这大约是 Vint Cerf 创建 IP 前身的时间(1970 年代)。我严重怀疑他们甚至不知道对方或对方在做什么,而且可以肯定的是,即使在他们制成产品(1980 年的以太网和 1981 年的 IPv4)之后,谁也不知道对方会成为主导。其他人和其他公司开发了其他数据链路协议,每个协议都具有由协议设计者指定的不同 MTU。

IP 和其他网络协议是数据链路协议的有效载荷,因此 IP 数据包必须适合数据链路协议的有效载荷 (MTU)。IP 设计为具有最大数据包大小,因为使用 16 位数字作为数据包大小既快速又容易。IPv4 有一个 20 到 60 个八位字节的标头,您必须从数据包大小中减去它。IPv6 有一个 40 个八位字节的标头和可能的选项标头。

传输协议,例如 UDP 或 TCP,是网络协议的有效载荷。UDP 的数据报头大小为 8 个八位字节,而 TCP 的段头至少为 20 个八位字节。

必须从数据链路协议 MTU 中减去网络协议和传输协议标头,以达到可以在数据链路帧内传输的最大应用程序数据量。这将包括任何应用层协议,例如 HTTP。


我想您缺少的部分是网络协议基本上都是由不同的人在不同的时间以不同的想法独立开发的。由于某种原因,我们今天使用的是多年来占据主导地位的协议。其中许多协议彼此无关。例如以太网可以承载任意数量的网络协议(IPv4、IPX、AppleTalk、IPv6等,以太网主要用于IPX多年,与IP无关),没有IP版本(IPv4和IPv6)关心承载它的数据链路协议(以太网、Wi-Fi、ARCNET、令牌环、FDDI、帧中继、HDLC、PPP、ATM 等)。