TCP/IP协议族核心协议数据包长度探究

TCP/IP协议族核心协议数据包长度探究

一、MAC 帧

MAC 帧中非数据部分的长度一共是 18(6+6+2+4)个字节,而总长度限制范围是 64 ~ 1518,那么 MTU 数据部分的长度就为 46 – 1500字节。

以太网V2中MAC帧格式
以太网V2中MAC帧格式

1、为什么总长度限制最小64呢?

早期总线以太网(IEEE 802.3标准)使用 CSMA/CD协议,多台设备共享信道,同时发送信号时需要进行碰撞检测。短帧发送时间也很短,如果给一个很远的主机发送信号,很可能在发送完后都没有检测出碰撞,因为电磁波的传输也有速度限制。如果这个时候发生了碰撞,发送方是不知道的,不会重发这个帧。

为了避免发生这种情况(小帧碰撞但是不重发),发送帧的时间就不能太短,最少需要一个争用期(51.2us)。对于 10Mbits/s 以太网,争用期可以发送 64个字节(512 bit数据)。以太网在发送数据时,如果在争用期(共发送了64字节)没有发生碰撞,那么后续发送的数据就一定不会发生冲突。64个字节去掉 非数据部分的 18个字节,则 最小 MTU 为 46 。

2、为什么总长度最大是1518?

最常用的以太网规定 MTU 值为 1500,最大值即时 1518。

如果太大(比如 MTU 65553)的话,比如会有什么问题?

  • 早期总线结构下,会导致发送时间过长,独占链路时间长,对其他主机的通信会产生严重影响。

早期在 10Mbit/s 的总线以太网上,发送 65553 Byte(IP数据报理论最大长度 65535+ MAC帧非数据部分 18)的数据会占用链路长度 50ms 时间,(65553 8) / ( 10 1024 * 1024 ) ≈ 0.05s (50ms)

  • 以太网帧中简单的CRC32错误检测时,更容易遭受未检测到的错误——因为更多的数据增加了几个错误互相抵消的概率。
  • 帧越大,丢失重传的代价越高,网络负担重。

如果数据帧太小的话,有什么问题?

  • 最大的问题是传输效率低,TCP 包头20 + IP 包头20 + MAC 数据帧头尾 18 就已经是 58 字节了了。

如果取值 1500,计算 TCP 报文来说,传输效率约为 (1500 – 20 -20)/ 1518 = 96%。1500这个值,对效率来说还是不错的。

当然你可以说取更高一点的值(比如 2000、2500),不行么?也可以但是得经过标准组织通过呀。

未来说不定为了进一步提高效率,可能会将大部分设备 MTU 提高。

3、现在还需要最大最小限制么?

由于目前以太网已经不使用总线拓扑了,没有了碰撞问题,其实没有必要再限制最小帧长了

至于最大值限制,现在很多千M以太网或者更高带宽以太网为了提高传输效率,会使用巨型帧。

未来如果常规网络带宽真的提高巨大,为了效率,提高 MTU 的值也是很有可能的。但是同时会带来的问题就是对帧检验错误的能力会降低,需要额外机制来改进错误检测。显然升级数量巨大的以太网基础设施是十分困难的。还要看如何权衡这个利弊。

巨型帧当前有少量实际的应用,但是因为上面的一些问题,尚未成为官方的IEEE 802.3以太网标准的一部分。目前绝大部分以太网 MTU 规定仍是 1500。

二、IP 数据报

IPv4数据报格式
IPv4数据报格式

IP 数据报中首部长度(Header Length)字段占用了 4 位,能表示的最大值的 15。但是这个字段的单位 32位长( 4个字节),所以首部最大长度为 15*4=60 字节。其最小值为5,因为首部固定部分 20 字节。

由于 IP 数据报首部格式固定部分长度为 20字节,那么 可选项部分(Option)最大长度为 40个字节

IP 数据报中总长度(Total Length)占了 16 位,最大值是 2^16 -1 = 65535 字节,但是实际中这么大的数据报是极少见的。注意这里的总长度包括了当前报文段的首部和数据部分

另外,总长度 – 首部长度 = 数据部分长度,也就是传输层 TCP 或 UDP 报文分组的长度。

1、IP数据报分片

所发送的 IP 数据报如果超过的链路层的 MTU值,就必须进行分片传输。IP 数据报支持分片传输,但是在实际使用中我们要避免分片。为什么要避免分片?

  • IP层没有重传机制,如果某个分片丢失,传输层需要将所有分片进行重传。
  • 多个分片都会有自己的 IP 首部,实际数据部分比例下降,数据传输效率会降低。

一般 TCP 建立连接时会相互通知 MSS 值(TCP报文的 Option 中),从而避免分片。

UDP需要应用层去现在包大小,MTU最大 1500,需要限制 UDP包不超过 1472 (1500 – IP包头20 – UDP包头8)

2、MSS 值是多少?

一般来说,只要避免 IP 分片,TCP 的 MSS 值可以尽量大一些。但是网络情况是复杂的,IP数据报经历的路劲是会动态变化的,最佳的 MSS 确认是不太容易的。如果双方没有相互通知 MSS ,那个需要一个保守的值,再加上一些历史原因,于是默认的 MSS 定为 576。

如果使用TCP协议,实际中在连接阶段很多相互通知 MSS 的值为 1460(MTU 1500 – IP header 20 – TCP header20

三、UDP用户数据报

UDP用户数据报首部格式
UDP用户数据报首部格式

UDP header 长度为8个字节。很多人觉得UDP header 中的 length 字段其实是冗余的,因为它等于IP Total length 减去IP header length。因为刚好空出来的这个位置,就放长度了。

四、TCP报文段

TCP 报文首部格式
TCP 报文首部格式

TCP 报文段格式内是没有长度的,其长度可以通过 IP 首部中长度推算出来。

实际中,在连接阶段很多相互通知 MSS 的值为 1460(MTU 1500 – IP header 20 – TCP header20)。如果没有通知 MSS,则默认的 MSS 为 576,一个很保守的值。

五、wireshark抓包

TCP连接阶段MSS通知
TCP连接阶段MSS通知

建立连接阶段,OPTION中的 MSS 为 1460。

TCP连接请求应答
TCP连接请求应答

这里是一个 TCP 请求连接请求的 ACK 报文段,我们看到 frame 长度 54 bytes (54 = Ehernet 14 +IP header 20+ TCP header 20)。问题来了,数据帧最小不是 64字节么?

网卡在工作时要先去掉前导同步码和帧开始定界符,然后对帧进行差错检验,如果帧校验和错,就丢弃此帧。如果校验和正确,就判断帧的目的硬件地址是否符合自己的接收条件(目的地址是自己的物理硬件地址、广播地址、可接收的多播硬件地址等),如果符合,就将帧交“设备驱动程序”做进一步处理。这时我们的抓包软件才能抓到数据。

因此,wireshark 抓到的是去掉前导同步码、帧开始分界符、CRC校验之外的数据。而实际传输的帧大小应该是 54 + 8 + 4 =66字节。

六、其他

1、参考

ITEF rfc791 -INTERNET PROTOCOL 
以太网为什么要限制最小帧长?
知乎-为什么以太网无法接收大于1500字节的数据包?
什么是MTU?为什么MTU值普遍都是1500?
知乎-TCP 中的MSS是 536
百度百科-巨型帧)
TCP 、UDP、IP包的最大长度是多少?

2、环境信息

wireshark版本

Version 2.2.0 (v2.2.0-0-g5368c50 from master-2.2)

系统版本

macOS High Sierra 10.13.3

发表评论

电子邮件地址不会被公开。 必填项已用*标注