3、IP协议详解:IPv4报文结构、IP分片与重组、子网划分与CIDR、IPv6基础与调试
IP协议,说白了就是网络世界的「地址系统」。没有它,数据包就像没有收件人的快递,满世界乱跑。我做了这么多年嵌入式网络开发,调试IP层的问题是最多的——不是报文格式错了,就是分片没处理好,要么就是子网掩码配错了。今天咱们就把IP协议这块硬骨头啃下来。
3.1 IPv4报文结构:别被20字节吓到
IPv4报文头部固定20字节,后面跟选项字段(最多40字节)。我刚开始看这个结构时,觉得字段太多了。其实真正需要关注的,就那么几个。
| 字段 | 长度(位) | 说明 |
|---|---|---|
| 版本 | 4 | IPv4就是4,IPv6就是6 |
| 首部长度 | 4 | 单位是4字节,最小5(20字节) |
| 总长度 | 16 | 整个IP报文长度,最大65535字节 |
| 标识 | 16 | 分片时用,同一报文分片标识相同 |
| 标志 | 3 | DF(不分片)、MF(还有分片) |
| 片偏移 | 13 | 分片在原报文中的偏移,单位8字节 |
| 生存时间 | 8 | TTL,每经过一个路由器减1 |
| 协议 | 8 | 上层协议:1=ICMP,6=TCP,17=UDP |
| 首部校验和 | 16 | 只校验头部,不校验数据 |
| 源IP地址 | 32 | 发送方IP |
| 目的IP地址 | 32 | 接收方IP |
3.2 IP分片与重组:嵌入式设备最容易踩的坑
为什么需要分片?因为链路层有MTU限制。以太网MTU是1500字节,Wi-Fi通常是1500,有些PPP链路只有576。IP层发现报文超过MTU,就得切碎它。
分片规则其实不复杂:
- DF=1时,不分片。如果报文太大,直接丢弃并返回ICMP错误
- DF=0时,可以分片。每个分片都有相同的标识字段
- 除了最后一个分片,其他分片的MF=1
- 片偏移是8字节的倍数
重组时,接收端需要:
- 根据标识字段,把属于同一报文的分片归到一起
- 根据片偏移,按顺序排列
- 检查MF位,直到收到MF=0的分片
- 如果某个分片超时未到,丢弃整个报文
嗯,这里要注意:嵌入式设备内存有限,重组缓冲区不能太大。我一般建议设置成最大报文长度65535字节,但实际中很少用到这么大。如果内存紧张,可以限制只重组小于2048字节的报文。
3.3 子网划分与CIDR:别再死记硬背了
子网划分,说白了就是把一个大网络切成小网络。CIDR(无类别域间路由)则是用「IP地址/前缀长度」的方式来表示网络。
举个例子:192.168.1.0/24,表示前24位是网络号,后8位是主机号。这个网络有256个地址,但可用的是254个(去掉网络地址和广播地址)。
我刚开始学的时候,总是记不住子网掩码。后来发现一个规律:
- /24 对应 255.255.255.0
- /16 对应 255.255.0.0
- /8 对应 255.0.0.0
- /30 对应 255.255.255.252(只有2个可用地址,常用于点对点链路)
192.168.1.100/24,比写子网掩码255.255.255.0更直观。很多轻量级协议栈(如LwIP)都支持这种格式。
子网划分的实战场景:
- 公司有4个部门,每个部门不超过50台设备
- 分配一个/24网络(256个地址),切成4个/26子网(每个64个地址)
- 每个子网可用地址62个,够用了
你想想看,如果不划分子网,所有设备都在一个广播域里,ARP广播满天飞,网络性能肯定受影响。
3.4 IPv6基础与调试:迟早要面对
IPv6地址128位,写成8组16进制数。比如:2001:0db8:85a3:0000:0000:8a2e:0370:7334。可以省略前导0,连续0可以用::代替(只能一次)。
IPv6和IPv4最大的区别:
- 没有广播地址,用组播代替
- 没有NAT,理论上每个设备都有公网IP
- 自动配置(SLAAC)比DHCP更常用
- 头部固定40字节,没有选项字段(用扩展头部代替)
ping6和traceroute6。在嵌入式设备上,我习惯先检查链路本地地址(fe80::/10)是否配置成功。如果链路本地地址都不通,那全局地址肯定也通不了。
IPv6的调试要点:
- 先确认设备是否支持IPv6(很多嵌入式协议栈默认只开IPv4)
- 检查邻居发现协议(NDP)是否正常工作
- 确认路由器通告(RA)是否到达设备
- 测试链路本地地址通信
我曾经调试过一个物联网项目,设备死活获取不到IPv6地址。抓包一看,路由器通告报文到了,但设备没响应。最后发现是协议栈的NDP实现有bug——没有正确处理RA报文中的前缀信息选项。修了3行代码就好了。
最后说一句:IPv6迟早要全面铺开。现在嵌入式设备如果不支持IPv6,过几年可能就卖不出去了。我建议你在新项目中,至少把IPv6的链路本地通信做起来,这是最低要求。