》引入IP分片的原因:
在数据链路层,以太网和802.3对数据帧的长度都有一个限制,最大长度为1500和1492个字节,这个特性称为MTU。当IP层的数据报要传向数据链路层,并且比MTU大,则这时就需要对数据报进行分片,把数据报分成若干片,每一片都小于MTU。
》IP层如何对数据报进行分片:
IP分片发生在IP层,不仅源端主机会进行分片,源端网络也会分片。不同网络的MTU不同,当目标网络的MTU小于源网络,路由器就会对IP数据报进行分片。分片数据的重组发生在目的端的IP层。
在IP首部有4个字节是用于分片的,如下图所示。前16位是IP数据报的标识,同一个数据报的各个分片的标识是一样的,目的端会根据这个标识来判断IP分片是否属于同一个IP数据报。中间3位是标志位,其中有1位用来表示是否有更多的分片,如果是最后一个分片,该标志位为0,否则为1。后面13位表示分片在原始数据的偏移,这里的原始数据是IP层收到的传输的TCP或UDP数据,不包含IP首部。
需要注意的,在分片的数据中,传输层的首部只会出现在第一个分片中,如下图所示。因为传输层的数据格式对IP层是透明的,传输层的首部只有在传输层才会有它的作用,IP层不知道也不需要保证在每个分片中都有传输层首部。所以,在网络上传输的数据包是有可能没有传输层首部的。
》三位标志:
第一位是为以后用准备;第二位表示是否分片,若为1则不进行分片,如果这个数据报不能通过网络转发,则丢弃,若为0,则在需要时对数据报进行分片;第三位表示“更多分片”,若为1,则表示还有分片,若为0则为最后一个分片。
》如何避免IP分片?
在网络编程中,我们要避免IP分片,原因是IP层是没有超时重传机制的,如果IP层对一个数据包进行了分片出现差错,少传之类的,则需要从TCP层重新进行传输,需要将整个数据包,所有分片都进行重传,这个代价特别大,由此可见,IP分片会大大的降低传输层传输数据的成功率,所以我们就要避免IP分片。
对于UDP包,我们需要在应用层限制每个包的大小,一般不要超过1472个字节,即1500-UDP头部(8)-IP头部(20)。
但是对于TCP包,应用层则没有必要考虑包大小的问题,因为传输层已经做了这个事情。在建立三次握手的过程中,连接双方会相互通知MSS(Maximum Segment Size,最大报文段长度),MSS一般是MTU-IP首部(20)-TCP首部(20),每次发送的TCP数据都不会超过超过双方的MSS的最小值,所以就保证了IP数据报不会超过MTU,避免了IP分片。
》IP分片重组:
IP分片的重组发生在目的主机的IP层,接收主机在第一个分片到达时会分配一个存储缓冲区,与此同时,主机还会启动一个计数器,接下来到达的分片会根据存储区中的偏移量指定的位置进行重组,直到没有分片。
如果计数器超时或者分片保持尚未认可状态,则数据报会被丢弃。
如何重组:在接收方将分片重组好才可以交给上层协议,待重组的分片用一个ipd结构来保存。
为了高效的进行分片重组,ipd结构需要做到以下几点:
1.快速的定位某个数据报的一组所有分片
2.快速的在正确的数据报中插入新的分片
3.有效的判断某一个数据报的所有分片是否全部接收
4.具有组装超时机制,如果在未完成组装时计时器溢出,则抛弃该组分片。