TCP/IP协议如何实现ip分片
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,小编给大家分享一下TCP/IP协议如何实现ip分片,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!分析一下ip分片。首先我们
千家信息网最后更新 2026年11月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安全错误
数据库的锁怎样保障安全
科技金融是不是互联网金融
互联网科技财经
美国互联网科技巨头监管
网络科技有限互联网
深圳互联网络科技有限公司
齐家互联网科技
互联网科技公司官网
无线互联网科技
互联网科技公司介绍
金融科技和互联网金融
苏州铭阳互联网科技有限公司
民营互联网公司国防科技
天津腾达互联网科技有限公司
西安小鹰速贷互联网科技有限公司
广州百诚互联网科技有限公司官网
上海创道互联网络科技有限公司
互联网时代高科技布局
玉溪新华互联网科技怎么选
安徽零酒互联网科技有限公司
优雇互联网科技有限公司
手冲咖啡和咖啡机区别
互联网科技有限公司
互联网是第几次科技革命的成果
互联网科技公司经营范围
互联网科技工作委员会主任
互联网金融科技平台
金融科技和互联网金融
以后互联网后是啥科技
华服互联网科技官网
瑞安市蟠桃会互联网科技有限公司