前言
在使用UDP传输的时候,每次接收的最大字节数为1472个字节,然后数据就会被分包,重新进行发送,在进行数据接收的时候,经常会遇到本次数据还没有接收完,数据就被分包的情况,那么为什么是1472个字节对数据进行分片呢,我们下面做一个详细的介绍。
TCP/IP协议 数据传输封装过程
首先要看TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层。 其中以太网(Ethernet)的数据帧在链路层
当我们应用程序用TCP/UDP传输数据的时候,数据被送入协议栈中,然后逐个通过每一层,直到最后到物理层将数据帧转换成比特流,送入网络。而在这个过程中,每一层都会对要发送的数据加一些首部信息。整个过程如下图,每层数据向下传输时都会进行封装,帧有效数据来源于上级网络层。
如图可以看出,每一层数据是由上一层数据+本层首部信息组成的,其中每一层的数据 ,称为本层的协议数据单元 ,即PDU.
应用层 数据在传输层添加TCP报头后得到的PDU被称为 Segment(数据段 ),图示为TCP段传输层 的数据(TCP段)传给网络层,网络层添加IP报头得到的PDU被称为Packet(数据包); 图示为IP数据包网络层 数据报(IP数据包)被传递到数据链路层,数据链路层 数据称为Frame(数据帧),图示为以太网帧。- 最后,帧被转换为
比特 ,通过网络介质传输。这种协议栈逐层向下传递数据,并添加报头和报尾的过程称为封装。
不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报(datagram),在链路层叫做帧(frame)。数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,最后将应用层数据交给应用程序处理。
以太网数据帧
我们再来看下以太网数据帧的格式
-
目的物理地址(DMAC):是目的MAC地址。长度为6个字节 -
源物理地址(SMAC):是源MAC地址。长度为6个字节 -
类型( Ethernet II): 用于标识以太网首部后面所跟数据包的类型。 -
数据部分(Payload):数据也叫有效载荷,这是网络层传递给数据链路层的帧,其长度为 46-1500 Bytes。 -
数据校验字段(CRC),用于存储 CRC(循环冗余校验)结果的帧的帧尾。
以太网帧 的长度在64-1518字节之间。
最小数据帧:6(目的MAC) + 6(源MAC) +2(类型)+ 46(数据帧) + 4 (CRC) = 64 字节
最大数据帧:6(目的MAC) + 6(源MAC) +2(类型)+ 1500(数据帧) + 4 (CRC) = 1518 字节
UDP传输
UDP是面向数据报的传输层协议,即进程的每个输出操作刚好产生一个UDP数据报,并组装成一份待发送的IP数据报。
UDP数据报封装成IP数据报的格式如图所示:
UDP首部
UDP首部格式如图所示:
- 端口号表示发送进程和接收进程。(IP数据报根据协议字段值区分是UDP或TCP)
- UDP长度字段是UDP首部和UDP数据的字节长度。最小值为8,即可以发送一份数据长度为0字节的UDP数据报
- UDP校验和覆盖UDP首部和UDP数据。(IP数据报中校验和是首部校验和,不涉及数据)UDP的校验和是可选的,而TCP的校验和是必须的。
MTU
其次我们要了解什么是MTU,Maximum Transmission Unit(MTU):最大传输单元。
MTU的含义: MAC帧内的数据(Payload)字段的最大长度。就是单次传输中能够传输的最大数据长度
对于以太网来说。其单次传输数据帧 最大长度为1500字节
问题解决:
在应用程序中我们用到的数据Data的长度最大是多少,直接取决于底层的限制。
根据上面的知识,我们可以分析一下:
- 在链路层,由以太网的物理特性决定了数据帧的长度为64 (46+18) ~ 1518 (1500+18),其中的18是数据帧的头和尾,也就是说数据帧的内容最大为1500(不包括帧头和帧尾),即MTU(Maximum Transmission Unit)为1500;
- 在网络层,因为IP包的首部要占用20字节,所以这的MTU为1500-20=1480;
- 在传输层,对于UDP包的首部要占用8字节,所以这的MTU为1480-8=1472;
所以,在应用层,数据Data最大长度为1472。当我们的UDP包中的数据多于MTU(1472)时,发送方的IP层需要分片fragmentation进行传输,而在接收方IP层则需要进行数据报重组,由于UDP是不可靠的传输协议,如果分片丢失导致重组失败,将导致UDP数据包被丢弃。
IP分片带来的问题
IP分片其实在网络中是一种比较糟糕的情况,带来了几个问题
-
传输效率降低:分片会降低传输效率,接收方IP层则需要进行数据报的重组 -
丢包:由于UDP的特性,当某一片数据传送中丢失时,那其余接收到的数据就没任何意义了,组不成一个完整的数据包,将导致丢弃整个UDP数据报
|