IP分片

IP分片浅析
在TCP/IP分层中,数据链路层用MTU(Maximum Transmission Unit,最大传输单元)来限制所能传输的数据包大小,MTU是指一次传送的数据最大长度,不包括数据链路层数据帧的帧头,如以太网的MTU为1500字节,实际上数据帧的最大长度为1512字节,其中以太网数据帧的帧头为12字节。
当发送的IP数据报的大小超过了MTU时,IP层就需要对数据进行分片,否则数据将无法发送成功。

IP分片的实现
IP分片发生在IP层,不仅源端主机会进行分片,中间的路由器也有可能分片,因为不同的网络的MTU是不一样的,如果传输路径上的某个网络的MTU比源端网络的MTU要小,路由器就可能对IP数据报再次进行分片。而IP分片数据的重组只会发生在目的端的IP层。

一、分片信息在IP头中位置如下红色区域所示,占用4字节

二、各字段详细含义如下图所示

1、Identification (16位) IP数据报的标识,同一个数据报的各个分片的标识是一样的,目的端会根据这个标识来判断IP分片是否属于同一个IP数据报。
2、R:保留未用。
3、DF:Don’t Fragment,“不分片”位,如果将这一比特置1,IP层将不对数据报进行分片
3、MF:More Fragment,“更多的片”,除了最后一片外,其它每个组成数据报的片都要把比特置1。
4、Fragment Offset (13位)分片在原始数据的偏移,这里的原始数据是IP层收到的传输的TCP或UDP数据,不包含IP首部。


需要注意的,在分片的数据中,传输层的首部只会出现在第一个分片中,如下图所示。因为传输层的数据格式对IP层是透明的,传输层的首部只有在传输层才会有它的作用,IP层不知道也不需要保证在每个分片中都有传输层首部。所以,在网络上传输的数据包是有可能没有传输层首部的。


避免IP分片
在网络编程中,我们要避免出现IP分片,那么为什么要避免呢?原因是IP层是没有超时重传机制的,如果IP层对一个数据包进行了分片,只要有一个分片丢失了,只能依赖于传输层进行重传,结果是所有的分片都要重传一遍,这个代价有点大。由此可见,IP分片会大大降低传输层传送数据的成功率,所以我们要避免IP分片。
对于UDP包:   需要在应用层去限制每个包的大小,一般不要超过1472字节,即以太网MTU(1500)—UDP首部(8)—IP首部(20)。
对于TCP数据: 应用层就不需要考虑这个问题了,因为传输层已经帮我们做了。在建立连接的三次握手的过程中,连接双方会相互通告MSS(Maximum Segment Size,最大报文段长度),MSS一般是MTU—IP首部(20)—TCP首部(20),每次发送的TCP数据都不会超过双方MSS的最小值,所以就保证了IP数据报不会超过MTU,避免了IP分片。

IP分片实例
1. UDP
从10.224.142.166向10.137.133.101发送3000字节的UDP数据,抓包的结果如下图。从图中可以看到这个UDP数据包被分成了3个IP片,从各分片的偏移量可以看出,3片包含的UDP数据大小分别是1480、1480、48(加上UDP首部8个字节),各分片加上IP首部的大小分别就是1500、1500、68,传送的总的UDP数据大小为3008,由此也看出只有一个分片包含UDP首部。

2. TCP
从10.224.142.166向10.137.133.101发送2000字节的TCP数据,抓包的结果如下图。从图中可以看出TCP数据被分成了2个IP片,包含的数据大小分别为1448、552,从三次握手可以看出双方通告的MSS都是1460字节,刚好是MTU(1500)—IP首部(20)—TCP首部(20),但实际为什么第一个分片只发送了1448字节呢,个人觉得应该是TCP首部还有一些选项占用了12个字节,也请知道的达人解释一下。


参考资料:
IP分片浅析 http://www.cnblogs.com/glacierh/p/3653442.html
ip分片重组及tcp分段重组具体实现   http://download.csdn.net/detail/u013498580/9423555
MTU和IP分片   http://www.cppblog.com/smagle/archive/2011/03/04/141129.html

深入理解IP包分片原理.doc http://www.docin.com/p-473800252.html



猜你喜欢

转载自blog.csdn.net/u014279330/article/details/78432845