<p>Arrays.copyOfRange 不适合直接提取 IP 头部关键选项字节;需先解析 IHL 字段(ipBytes[0] 右移 4 位并 & 0xF),再计算 optionsStart = 20、optionsLen = ihl * 4 - 20,最后安全截取。</p>

Java 的 Arrays.copyOfRange 本身并不适合直接提取 IP 报文头部的“关键选项字节”,因为它只是一个通用数组截取工具,不具备协议解析能力。真正高效提取 IP 头部选项字段,关键在于:先正确解析 IP 头部结构(尤其是首部长度 IHL 和选项是否存在),再结合原始字节数组的偏移位置,用 copyOfRange 安全截取目标范围——而不是盲目调用。
明确 IP 头部结构与选项位置
IPv4 头部最小长度为 20 字节(IHL = 5),每单位代表 4 字节;若 IHL > 5,说明存在选项字段,其起始位置固定为第 20 字节(索引 20),长度为 (IHL × 4) − 20。必须先从字节数组前 20 字节中解析 IHL 字段(位于第 1 字节高 4 位):
- 读取
ipBytes[0],右移 4 位并 & 0xF 得到 IHL 值 - 计算选项起始索引:
int optionsStart = 20 - 计算选项长度:
int optionsLen = (ihl (左移 2 位等价于 ×4) - 确保
optionsLen ≥ 0且optionsStart + optionsLen ≤ ipBytes.length
用 copyOfRange 精确截取选项字节
确认选项存在且长度合法后,才调用 Arrays.copyOfRange 提取原始字节数组中的对应片段:
byte[] options = Arrays.copyOfRange(ipBytes, optionsStart, optionsStart + optionsLen);- 该方法内部使用
System.arraycopy,性能接近原生复制,无额外对象开销 - 避免传入负索引或越界——务必提前校验 IHL 和总包长,否则抛
ArrayIndexOutOfBoundsException
跳过无效选项,按类型解析关键字段
IP 选项格式为:Type(1 字节)、Length(1 字节,仅对部分选项存在)、Data(变长)。并非所有选项都“关键”,常见需提取的包括:
立即学习“Java免费学习笔记(深入)”;
- Record Route(RR,Type=7):记录经过的路由器 IP,Length 字段指示总长度,Data 部分含多个 IPv4 地址
- Timestamp(TS,Type=68):含时间戳和 IP 地址列表,需根据 Flag 字段判断格式
- Security(Type=130):用于分级安全标识,常需提取 Security、Compartment、Handling 字段
提取后应遍历 options 数组,按 Type-Length-Value 规则逐项解析,跳过未知或长度不匹配的选项。
注意字节序与协议约束
IP 协议规定所有多字节字段使用网络字节序(大端),而 Java byte 是有符号的,解析时需谨慎处理:
- 读取 16 位字段(如 Length):
(options[i] & 0xFF) << 8 | (options[i+1] & 0xFF) - IP 地址(4 字节)直接按顺序提取,无需反转,但构造
InetAddress时需用ByteBuffer.wrap(options, offset, 4).getInt()或手动拼接 - 选项总长度不能超过 40 字节(IPv4 头部最大 60 字节),超出即非法,应拒绝解析


















