知识点编号:027
难度等级:⭐⭐(了解)
面试频率:🔥🔥
🎯 一句话总结
IP报头就像信封,上面写着发件人、收件人、邮戳等信息!📮
📦 IPv4报头结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|版本(4)| 头长度(4)|服务类型(8)| 总长度(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 标识(16) |标志(3)| 片偏移(13) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TTL(8) | 协议(8) | 头部校验和(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源IP地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目标IP地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(可变长度) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
最小长度:20字节
最大长度:60字节(包含选项)
🔍 字段详解
1. 版本(Version,4位)
值:4(IPv4)或 6(IPv6)
示例:
0100 = 4 (IPv4)
0110 = 6 (IPv6)
作用:区分IP版本
2. 头长度(Header Length,4位)
单位:4字节
范围:5-15(20-60字节)
计算:
值=5 → 5×4 = 20字节(最小)
值=15 → 15×4 = 60字节(最大)
示例:
0101 = 5 → 20字节头部
0110 = 6 → 24字节头部(有4字节选项)
3. 服务类型(Type of Service,8位)
已废弃,现用于:
- 3位:优先级
- 4位:服务类型(D-低延迟、T-高吞吐、R-高可靠、C-低成本)
- 1位:保留
现代:
用DSCP(Differentiated Services Code Point)
实现QoS(服务质量)
4. 总长度(Total Length,16位)
整个IP包的长度(头部+数据)
单位:字节
范围:20-65535字节
示例:
总长度 = 1500字节
头长度 = 20字节
数据长度 = 1500 - 20 = 1480字节
5. 标识(Identification,16位)
用于分片重组
同一个包的所有片有相同标识
示例:
原包:标识=12345
片1:标识=12345
片2:标识=12345
片3:标识=12345
接收方根据相同标识重组
6. 标志(Flags,3位)
bit 0:保留,必须为0
bit 1:DF(Don't Fragment)- 不分片
bit 2:MF(More Fragments)- 还有更多片
示例:
DF=1, MF=0:不允许分片
DF=0, MF=1:允许分片,且还有更多片
DF=0, MF=0:最后一片或没分片
7. 片偏移(Fragment Offset,13位)
单位:8字节
表示该片在原包中的位置
示例:
片1:偏移=0(0字节)
片2:偏移=185(185×8=1480字节)
片3:偏移=370(370×8=2960字节)
8. TTL(Time To Live,8位)
生存时间,每跳减1
范围:0-255
常见值:
64:Linux/Mac
128:Windows
255:路由器
9. 协议(Protocol,8位)
上层协议类型
常见值:
1:ICMP
6:TCP
17:UDP
41:IPv6
89:OSPF
示例:
协议=6 → 上层是TCP
协议=17 → 上层是UDP
10. 头部校验和(Header Checksum,16位)
只校验IP头部,不校验数据
计算:
1. 把头部分成16位的字
2. 全部相加
3. 结果取反码
验证:
接收方重新计算校验和
如果不匹配,丢弃包
11. 源IP地址(32位)
发送方的IP地址
示例:
192.168.1.10
→ 二进制:11000000.10101000.00000001.00001010
12. 目标IP地址(32位)
接收方的IP地址
示例:
8.8.8.8
→ 二进制:00001000.00001000.00001000.00001000
13. 选项(Options,可变长度)
可选字段,很少使用
常见选项:
- 记录路由(Record Route)
- 时间戳(Timestamp)
- 松散源路由(Loose Source Routing)
- 严格源路由(Strict Source Routing)
长度:0-40字节
💻 Java解析IP头部
public class IPHeaderParser {
public static void parseIPHeader(byte[] packet) {
// 版本和头长度(第1字节)
int versionAndLength = packet[0] & 0xFF;
int version = (versionAndLength >> 4) & 0x0F;
int headerLength = (versionAndLength & 0x0F) * 4;
System.out.println("版本: " + version);
System.out.println("头部长度: " + headerLength + " 字节");
// 服务类型(第2字节)
int tos = packet[1] & 0xFF;
System.out.println("服务类型: " + tos);
// 总长度(第3-4字节)
int totalLength = ((packet[2] & 0xFF) << 8) | (packet[3] & 0xFF);
System.out.println("总长度: " + totalLength + " 字节");
// 标识(第5-6字节)
int id = ((packet[4] & 0xFF) << 8) | (packet[5] & 0xFF);
System.out.println("标识: " + id);
// 标志和片偏移(第7-8字节)
int flagsAndOffset = ((packet[6] & 0xFF) << 8) | (packet[7] & 0xFF);
boolean df = ((flagsAndOffset >> 14) & 0x01) == 1;
boolean mf = ((flagsAndOffset >> 13) & 0x01) == 1;
int offset = (flagsAndOffset & 0x1FFF) * 8;
System.out.println("DF标志: " + df);
System.out.println("MF标志: " + mf);
System.out.println("片偏移: " + offset + " 字节");
// TTL(第9字节)
int ttl = packet[8] & 0xFF;
System.out.println("TTL: " + ttl);
// 协议(第10字节)
int protocol = packet[9] & 0xFF;
String protocolName = getProtocolName(protocol);
System.out.println("协议: " + protocol + " (" + protocolName + ")");
// 校验和(第11-12字节)
int checksum = ((packet[10] & 0xFF) << 8) | (packet[11] & 0xFF);
System.out.println("校验和: " + Integer.toHexString(checksum));
// 源IP地址(第13-16字节)
String srcIP = String.format("%d.%d.%d.%d",
packet[12] & 0xFF,
packet[13] & 0xFF,
packet[14] & 0xFF,
packet[15] & 0xFF
);
System.out.println("源IP: " + srcIP);
// 目标IP地址(第17-20字节)
String dstIP = String.format("%d.%d.%d.%d",
packet[16] & 0xFF,
packet[17] & 0xFF,
packet[18] & 0xFF,
packet[19] & 0xFF
);
System.out.println("目标IP: " + dstIP);
}
private static String getProtocolName(int protocol) {
switch (protocol) {
case 1: return "ICMP";
case 6: return "TCP";
case 17: return "UDP";
case 41: return "IPv6";
case 89: return "OSPF";
default: return "Unknown";
}
}
}
🐛 常见面试题
Q1:IPv4报头有哪些重要字段?
答案:
核心字段:
1. 版本(4位)- 区分IPv4/IPv6
2. 头长度(4位)- 头部大小
3. 总长度(16位)- 整个包大小
4. 标识(16位)- 分片标识
5. 标志(3位)- DF/MF
6. 片偏移(13位)- 分片位置
7. TTL(8位)- 生存时间
8. 协议(8位)- 上层协议(TCP/UDP)
9. 校验和(16位)- 头部校验
10. 源IP(32位)- 发送方地址
11. 目标IP(32位)- 接收方地址
最小长度:20字节
最大长度:60字节
Q2:IP头部校验和是如何计算的?
答案:
计算步骤:
1. 校验和字段设为0
2. 把IP头部分成16位的字
3. 所有字相加
4. 如果有进位,加到最低位
5. 结果取反码
示例:
头部:0x4500 0x003c 0x1c46 0x4000 0x4006 0x0000 ...
相加:0x4500 + 0x003c + 0x1c46 + ... = 0xb1e6
取反:~0xb1e6 = 0x4e19
校验和:0x4e19
验证:
接收方重新计算
如果结果是0xFFFF,校验通过 ✓
否则,头部损坏,丢弃 ✗
注意:
只校验IP头部,不校验数据
TCP/UDP有自己的校验和
🎓 总结
IP报头的关键点:
- 最小20字节:固定字段
- 最大60字节:包含选项
- 核心字段:源IP、目标IP、TTL、协议
- 分片字段:标识、标志、偏移
记忆口诀:
版本头长服务型 📋
总长标识加标志 🏷️
TTL协议校验和 ✅
源IP目标IP地址 📮
文档创建时间:2025-10-31