TCP/IP协议如何实现ip分片
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,小编给大家分享一下TCP/IP协议如何实现ip分片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!分析一下ip分片。首先我们
千家信息网最后更新 2025年12月01日TCP/IP协议如何实现ip分片
小编给大家分享一下TCP/IP协议如何实现ip分片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
分析一下ip分片。首先我们要先了解为什么需要分片。比如在以太网中,使用CSMA/CD协议(由网卡实现),他规定了一个链路层数据包(不包括mac头,但是这一版内核实现的时候是包括了mac头的大小)的最大值(MTU)和最小值。所以如果上层的包大于这个阈值就需要被分片。而分片和组包的实现是在ip层。我们看一下具体的逻辑。ip分片的逻辑在ip_fragment函数里实现。
void ip_fragment(
struct sock *sk,
struct sk_buff *skb,
struct device *dev,
int is_frag
)定义的一些变量。
struct iphdr *iph;
unsigned char *raw;
unsigned char *ptr;
struct sk_buff *skb2;
int left, mtu, hlen, len;
int offset;
unsigned long flags;
// mac首地址
raw = skb->data;
// ip头首地址,hard_header_len为mac头大小
iph = (struct iphdr *) (raw + dev->hard_header_len);
skb->ip_hdr = iph;
// ip头的大小,不包括数据部分
hlen = (iph->ihl * sizeof(unsigned long));
// ip包总大小减去ip层等于ip报文的数据长度,即需要分片的部分的大小
left = ntohs(iph->tot_len) - hlen;
// ip头+mac头
hlen += dev->hard_header_len;
// 每个分片的数据部分长度等于mac层的mtu减去mac头和ip头,即mac层的mtu包括了mac头、ip头、ip数据部分的总和。
mtu = (dev->mtu - hlen);
// 数据部分首地址
ptr = (raw + hlen); 判断是否可以分片。
// 设置了不能分片则发送icmp报文,可以对照ip报文格式看
if (ntohs(iph->frag_off) & IP_DF)
{
icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev->mtu, dev);
return;
}判断即将被分片的ip包是否本身也是一个分片。即经过了多次ip分片。
/*
该ip报文本身就是一个分片,现在需要进行再次分片,
偏移的首地址是该报文的首地址乘以8,因为再次被分片的报文,他的偏移是
基于原来未被分片的数据的偏移。而不是针对当前这个分片的偏移
*/
if (is_frag & 2)
offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
else
offset = 0开始处理分片。
// 还有则继续处理
while(left > 0)
{
// ip包默认承载的字节数,但是如果大于mtu的话则取小的值,即mtu
len = left;
// 大于mtu则还要分片,即只能承载mtu大小的字节,否则就是最后一个分片
if (len > mtu)
len = mtu;
/*
剩下的字节比mtu大的时候下面的判断会成立,
即剩下的字节还不能在这次发送完,还要继续分片
除8乘8即取8的倍数大小,不一定等于mtu
*/
if (len < left)
{
len/=8;
len*=8;
}
// len 为这一分片承载的数据大小
// 申请新的skb,大小为mac头+ip头+数据部分长度
if ((skb2 = alloc_skb(len + hlen,GFP_ATOMIC)) == NULL)
{
return;
}
skb2->arp = skb->arp;
skb2->free = 1;
// 总大小是mac头+ip头+数据部分长度
skb2->len = len + hlen;
// 指向刚分配的内存首地址,开始复制数据
skb2->h.raw=(char *) skb2->data;
save_flags(flags);
restore_flags(flags);
// ip地址
skb2->raddr = skb->raddr;
// raw指向mac头首地址,这里把mac报头和ip报头+选项都复制到skb中,ip选项应该只复制到第一个分片,这里会复制到每一个分片中
memcpy(skb2->h.raw, raw, hlen);
// 复制数据部分,长度为len,ptr指向原ip报文中数据部分的首地址,
memcpy(skb2->h.raw + hlen, ptr, len);
// 剩下需要分片的字节数
left -= len;
// 指向ip头首地址
skb2->h.raw+=dev->hard_header_len;
iph = (struct iphdr *)(skb2->h.raw);
// 设置该分片的偏移,除以8,见ip协议的规定
iph->frag_off = htons((offset >> 3));
/*
1. 还有数据,则置MF,还要更多分片
2. is_frag =1;说明该分片后面还有更多分片。
表示被分片的数据本身就是一个ip分片,即再分片。
所以该报文下的所有分片MF都是1。
*/
if (left > 0 || (is_frag & 1))
iph->frag_off |= htons(IP_MF);
// 更新数据指针和偏移
ptr += len;
offset += len;
// 发送分片
ip_queue_xmit(sk, dev, skb2, 2);
}
分片主要的逻辑是1 申请一个新的内存,把待分片报文中的mac头、ip头,复制到新内存,然后数据部分切一块继续复制到内存后面。如此,直到分片完毕
2 修改ip报文中的一些字段的值 ,比如MF。
3 调底层接口逐个发送分片
分片的逻辑不算复杂,不讲解的太详细了。
以上是"TCP/IP协议如何实现ip分片"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
数据
地址
大小
报文
部分
偏移
字节
长度
内存
指向
逻辑
就是
更多
篇文章
内容
再次
报头
时候
处理
复杂
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络安全法和刑法的关系
税务网络安全工作
功能访问管理器服务器
郑大数据库应用技术答案
软件开发质量及效率提升
服务器pe清除管理员密码
java项目使用什么数据库
网络安全法的六个关注
2u服务器拆装费用
天津网络安全论道
学网络安全的用处
绵阳市网络安全保卫支队号码
nginx检测服务器原理
吉林网络技术工程
深圳神州物联网络技术有限公司
现在什么数据库比较好用
张家口java微服务架构数据库
华为电脑可以做软件开发
基础计算用什么软件开发
mfc 读取注册表数据库
哈弗f 7听音乐连接不上服务器
服务器管理显示未激活码
中国电信软件开发面试题
软件开发里的里程碑
为什么数据库要加锁
数据库三种日期类型
迷你世界怎么把服务器弄崩溃
数据库连接池实现6
电脑服务器放在哪里
汕头汽车软件开发公司