pcap_open_offline() 是读取 pcap 文件的唯一可靠起点,需检查 errbuf、用 pcap_datalink() 确认链路层类型,pcap_next_ex() 返回 1 或 -2,时间戳为微秒级,解析需按协议逐层跳过头部并处理字节序,pcapng 文件不支持该函数。

用 libpcap/WinPcap 读取 pcap 文件最简路径
直接调用 pcap_open_offline() 是唯一可靠起点,别自己解析文件头——pcap 格式有 magic number、时戳精度(nanosecond vs microsecond)、字节序、link-layer header type 等变体,手撕极易出错。
实操建议:
-
pcap_open_offline("capture.pcap", errbuf)成功后,用pcap_datalink()确认链路层类型(如DLT_EN10MB表示以太网),这直接影响后续如何跳过链路层头 - 错误信息必须检查:
errbuf非空即失败,常见报错是文件损坏或不支持的 magic number(比如误把 pcapng 当 pcap) - Windows 下若用 Npcap,优先链接
libpcap.lib而非 WinPcap 的旧库,避免pcap_next_ex()返回 -1 却不设 errbuf
pcap_next_ex() 解析每个 packet 的关键细节
pcap_next_ex() 返回值不是布尔值,是 1(成功)、0(超时,pcap 文件里不会出现)、-1(错误)、-2(EOF)。对 pcap 文件,只可能遇到 1 或 -2。
实操建议:
- 务必用
const u_char*接收数据指针,别强转成char*或unsigned char*——某些平台会因符号性导致高位字节截断 - 时间戳在
struct pcap_pkthdr*中:注意ts.tv_sec和ts.tv_usec是微秒级;若文件是 nanosecond 精度(pcapng 或新版本 tcpdump),pcap_open_offline()仍按微秒暴露,实际纳秒值被截断 - 包长字段易混淆:
header->len是原始捕获长度(可能被 snaplen 截断),header->caplen是实际保存长度,解析 payload 前必须用caplen做边界检查
从 raw packet 数据提取 IP/TCP 头需手动偏移计算
libpcap 不提供协议解析,只给裸字节流。以太网帧为例:先判断 DLT_EN10MB,再跳过 14 字节以太头;若含 802.1Q VLAN,则需额外跳过 4 字节,且要检查 ether_type 字段是否为 0x8100。
实操建议:
- IP 头起始位置不是固定偏移:以太网下通常是 +14,但若有 VLAN 或 MPLS,必须逐层解析 ether_type 才能定位 IP
- TCP 头偏移由 IP 头的
IHL字段决定(单位是 32-bit 字,即 ×4),不能硬写 +20;IPv6 则无 IHL,需靠扩展头链表遍历 - 所有字段读取必须考虑网络字节序:
ntohs()/ntohl()不可省略,否则源端口、标志位等全错
pcapng 文件无法用 pcap_open_offline() 直接打开
这是最常踩的坑:tcpdump 新版本默认生成 pcapng,而传统 libpcap(0x0a0d0d0a,会返回 “unsupported capture file format” 错误。
实操建议:
- 先用
file capture.pcap或十六进制查看前 4 字节:pcap 是0xa1b2c3d4(或小端0xd4c3b2a1),pcapng 是0x0a0d0d0a - 升级到 libpcap ≥ 1.10 并确认编译时启用了 pcapng 支持(CMake 中
ENABLE_PCAPNG=ON),否则即使新版库也会静默降级为失败 - 若无法升级,用
tshark -F libpcap -r input.pcapng -w output.pcap转换,别信“重命名后缀就能用”的说法
真正麻烦的从来不是读文件,而是链路层类型判断、字节序处理和 pcapng 兼容性——这三个点漏掉任一个,解析出来的 IP 地址或端口都是错的。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











