什么是 IP 分片?IP 分片的作用是什么?

IP分片是指IP协议将一个大的数据包分割成多个较小的包进行传输的过程。

IP分片的主要作用是:

  1. 适应不同网络的MTU:不同的网络可能有不同的最大传输单元(MTU),通过 IP分片可以在网络层对包进行分割,使其符合各个网络的MTU限制。
  2. 更好的利用网络带宽:一个大的数据包可能会阻塞其他包的发送,通过分片可以提高网络利用效率。
  3. 较小的包丢失概率:一个大包丢失的概率较一个小包丢失的概率高,分片可以减少数据丢失。

IP分片的过程如下:

  1. 确定每个分片的长度,不能超过目的主机网络的MTU。
  2. 第一片包含IP头部,且分片偏移为0。其余分片使用自己的IP头部,分片偏移非0。
  3. 在重新组装时,接收方利用每个分片的源IP地址、目标IP地址和标识字段将它们重新组装成完整的IP数据报。
  4. 如果某个分片丢失,重传请求只需请求丢失的分片。

代码示例:

python
from random import randint

# IP分片
def fragmentation(ip_header, data):
    mtu = 576        # MTU 
    total_length = ip_header.total_length
    offset = 0

    ip_headers = []   # 分片IP头部
    fragments = []    # 分片

    while total_length > 0:
        length = min(total_length, mtu)   # 分片长度 

        # 构造分片
        frag = data[offset:offset+length]   
        fragments.append(frag)

        # 构造分片IP头部  
        ip_header.total_length = length    
        ip_header.fragment_offset = offset // 8  
        ip_headers.append(ip_header.pack()) 

        offset += length
        total_length -= length

    return ip_headers, fragments 

# 发送方  
ip_header = IPHeader('192.168.1.1', '192.168.1.2', 6, 2000)  
ip_headers, fragments = fragmentation(ip_header, data)

for ip_header, frag in zip(ip_headers, fragments): 
    datagram = ip_header + frag
    sock.sendto(datagram, ('192.168.1.2', 80))

# 接收方  
fragments = []

while True:
    msg, addr = sock.recvfrom(mtu + 20)   # 带IP头部的分片 
    ip_header = IPHeader(msg[:20])  

    # 使用标识字段判断是否属于同一数据报 
    if ip_header.identification == id:  
        fragments.append(msg[20:])   # 添加分片数据
    else:
        # 重新组装并处理上一数据报的分片 
        whole_packet = b''.join(fragments)
        handle_packet(whole_packet) 

        # 开始接收新数据报的分片
        id = ip_header.identification 
        fragments = [msg[20:]]