OSI各层数据包
从上图可知,从应用层到传输层到网络层再到数据链路层,数据包经过一层一层的包装。
MTU
MTU(最大传输单元)指的是IP协议封装的大小最大值,理论上这个值的大小是2^16=65536,但是通常与通信接口有关(网卡,串口等)。但是IP协议的最外层还有数据链路层封装,该层头部14个字节,尾部4个字节。
不同的网络MTU的值不同,参考如下:
最常见的就是以太网。
MTU查看命令: netstat -in
所以最大帧:
MTU(一般为1500) + 数据两路层帧头部14字节 + 数据两路层帧尾部4字节 = 1518字节
IP分包
如果IP数据报的大小超过MTU就会在IP层执行IP分包操作,将一个IP划分成多个IP分片,每一个分片都是一个独立的IP数据报。
来看一个例子:
应用层:HTTP协议长度为4960Byte
传输层:TCP数据包头部20Byte,加上嵌入HTTP的数据包,总长度4980Byte
网络层:IP数据包头部20Byte,加上嵌入TCP数据包,总长度5000byte
数据链路层:以太网数据包的data部分,最大长度MTU(1500Byte),但是IP数据包是5000Byte,需要分包,所以分包如下:
-------------
IPHead | DATA
20 | 1480
20 | 1480
20 | 1480
20 | 540
-------------
80 4980
分4个IP数据包,大小分别为1500,1500,1500,560Byte大小.当然经过数据链路层还要包装一层,如下:
--------------------------
HEAD | IPHead | DATA | END
14 | 20 | 1480 | 4
14 | 20 | 1480 | 4
14 | 20 | 1480 | 4
14 | 20 | 540 | 4
--------------------------
这样就完成分包,最终将这4个包发送出去。
TCP分包
大多数(TCP有时会)只有UDP数据包超过MTU大小才会使用IP分包,TCP数据包一般在传输层就可以分包。
这里首先要说下:MSS(Maxitum Segment Size)最大分段大小,它是 TCP 协议里面的一个概念。
TCP 在建立连接的时候,会协商双方的MSS值,通常这个 MSS 会控制在 MTU 以内:最大 IP 包大小减去 IP 和 TCP 协议头的大小。(其最终目的:就是尽量避免 IP 分片)
这样 TCP 就可以在自己这一层,把用户发送的数据,预先分成多个大小限制在 MTU 里的 TCP 包。每个 TCP 的分包,都完整了包含了 TCP 头信息,方便在接收方重组。
如果某些情况导致:已经分好的 TCP 分片,还是大于了 MTU,那就在 IP 层中,再执行一次分片。
这个时候如果数据丢了,那也只需要重传这一个 TCP 的分片,而不是整个原始的 50k 数据。
UDP数据包在IP分包
它并没有协商的能力,所以它只能直接把用户发送的数据,传给网络层(IP层),由网络层来进行分片。
对 网络层(IP层)来说:它并不知道上层传过来的数据,到底是 TCP 还是 UDP,它并不关心这个东西,也没有能力去区分。
如果发现数据过大,那么 IP 层会自动对数据进行切割,分包。
注意:每个TCP分片,都是包含了完整的 TCP 协议头,这样另一方收到包之后,可以方便重组,可以计算出到底哪个分片包丢了,然后重新传这个分片包。
UDP 数据过大,带来的问题
用 UDP 协议发送,那么如果网络发生了波动,丢失了某个 IP 包分片,对于 UDP 而言,它没有反馈丢失了哪个分片给发送方的能力,这就意味着:**50k 的数据全都丢失了,如果需要重传,就得再次完整的传递这 50k 的数据。**所以如果一个应用采用 UDP 来通讯,一般都会特意控制下单个包体的大小,从而提高传输效率。