ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

报文结构详解:从Wireshark抓包到CAN、MODBUS、电力规约实战解析

2026/10/5 7:20:36 拓冰建站 浏览量
报文结构详解:从Wireshark抓包到CAN、MODBUS、电力规约实战解析 想搞清楚报文到底是什么最直接的办法就是打开抓包软件看一眼。我第一次在Wireshark里看到那一堆十六进制数字时说实话是发懵的但等弄明白“这一串字符就是一台设备写给另一台设备的信”之后整个网络世界突然就通透了。报文说白了就是信息在设备之间传递时携带的“完整信封”——里面有收件人地址、发件人地址、内容正文还有防伪校验。无论是你用浏览器打开网页还是汽车仪表盘读取发动机温度背后都是无数报文在一来一回地“说话”。这篇东西就是帮你把这封信从里到外拆开看明白覆盖网络、CAN总线、MODBUS、电力规约等几大类常见报文既有原理也有实战解析步骤。1. 报文的“信封结构”每个字节都不是随便填的1.1 一封完整报文必须有三段在TCP/IP的语境里报文通常指协议栈某一层传输的数据单元比如IP报文、ICMP报文、TCP段。但跳出具体协议报文的结构永远逃不出三个部分首部Header、载荷Payload、尾部Trailer。用一个寄快递的类比首部就是快递单上的收发件信息载荷是箱子里的实际商品尾部是贴的封条和保价标识。收件人拿到包裹后先看快递单确认“这是给我的”然后拆箱验货最后检查封条有没有破损。报文也一样——接收方拿到一串字节先解析首部确认格式和目的地址再提取数据区内容最后用校验字段验证数据有没有被篡改或丢字节。以最常见的IP报文为例版本号、首部长度、服务类型、总长度、标识符、标志位、片偏移、TTL、协议号、源IP、目的IP这20个字节的前半段全是“快递单信息”。TTL字段尤其有意思它规定了这个包在网络上最多能经过多少台路由器每转发一次减1减到0就直接丢弃。这就好比快递员每经过一个中转站就在单子上划一道划满了就不准再送。1.2 为什么必须规定字段长度很多新手问过一个问题为什么不把所有信息用分隔符隔开像CSV那样直接传答案是效率。二进制报文里每个字段的起始位置和长度都是协议写死的解析器不需要去找分隔符直接按偏移量截取就行。一个字段的边界就是下一个字段的起点没有任何冗余。拿CAN总线报文举例标准帧的数据域固定最多8个字节CAN ID在标准帧里是11位扩展帧是29位。接收方从CAN控制器硬件层面就直接按位去取如果是文本形式光找分隔符就要浪费一个仲裁周期在发动机控制这种毫秒级实时场景里这种浪费是绝对不能接受的。所以报文的世界里一切都是为了“按地址取数”而设计的。提示看懂报文第一件事不是背字段表而是搞清楚“当前协议规定的每个字段起始位宽是多少”。手里拿一张协议规范对着十六进制数据一行一行套几次之后就熟了。2. 一次完整的ICMP报文拆解把十六进制翻译成人话2.1 抓包前必须做的事在PC网卡上开启Wireshark捕获听上去很简单但有个高频坑很多笔记本的无线网卡默认不开混杂模式你只能抓到发给本机的包连局域网里的广播包都看不全。检查路径在Wireshark的“捕获选项”把“以混杂模式捕获”勾上管理员权限启动这样才能看到这个网卡上所有经过的流量。抓ICMP有个便捷方法开抓包的同时在命令行执行ping。打开Wireshark后在过滤栏输入icmp所有Ping请求和回显应答就会只剩下来回两对包。2.2 逐字节解读一个回显请求下面是一段实际的ICMP Echo Request报文过滤出来之后双击数据包中间面板能看到分层结构最底下是十六进制视图。我直接把它复制出来按字节拆08 00 4d 5f 12 34 00 01 61 62 63 64 65 66 67 6808类型字段8代表回显请求0代表回显应答。这就是Ping的本体。00代码字段。对于Echo类型这里永远为0。4d 5f首部校验和。注意这是ICMP协议的校验和只管整个ICMP报文IP首部的校验和在上一层已经算过了。12 34标识符。Windows和Linux下通常是发起Ping进程的PID用来区分不同进程发出的请求。00 01序列号。每发一次Ping这个值递增1用来匹配请求和响应是否成对。61 62 63 64 65 66 67 68数据区在ASCII码里恰好对应字符串“abcdefgh”。Ping命令默认会带一段数据填充用来测试报文经过网络时的分片和时延。如果同时看应答包的序列号你会发现应答包里的数据区原样复制了请求包的数据。这是ICMP协议的设计逻辑回应者把请求内容完全镜像返回发送方才能确认收到的内容没有损坏。2.3 从报文看网络丢包率很多人用Ping的统计信息里“丢失0%”来判断网络健康但只看回显统计容易漏事。打开Wireshark用统计菜单里的“IO图表”功能把过滤条件设成icmp.type8请求包和icmp.type0应答包分别画两条曲线。当两条曲线出现明显的高度差时请求包发出去了但应答没回来这就说明目的地设备在回包过程中出了问题——最常见的有三类防火墙对ICMP做了限制、目的主机的协议栈异常、中间链路存在单向丢包。单向丢包最隐蔽从一个方向看完全正常反方向却丢得厉害这种必须靠抓包软件的曲线对比才能发现。注意Wireshark显示列表中如果看到No response seen之类的提示并不一定代表丢包也可能是对方静默丢弃了不该回应的包。要看真正的丢包必须同时观察请求和应答两侧的报文数量而不是只看有没有“应答”。3. 不同行业里的“信使”网络、总线与电力规约的报文差异3.1 常见报文的一眼辨识表报文类型典型协议帧结构特征常见工具应用场景网络报文IP/ICMP/ARP首部定长20字节字段偏移固定Wireshark路由交换、故障排查无线控制报文CAPWAP控制报文走UDP端口5246数据报文走5247Wireshark瘦AP与无线控制器通信CAN报文CAN 2.0A/B帧ID数据域最多8字节CRC15位CANoe、PCAN、周立功汽车ECU通信、工业设备LIN报文LIN 2.x报文头同步场PID响应数据校验CANoe、LIN调试器车门、车窗、空调等低速控制工控报文MODBUS RTU/TCPRTU有地址码功能码CRC16TCP有MBAP头Modbus Poll、WiresharkPLC与上位机通信电力报文IEC 101/104、SL651、698.45固定帧头帧尾控制域地址域数据域校验CANoe串口工具、规约测试仪变电站、电表集抄、水文监测3.2 CAN报文几台ECU用一张总线抢话CAN总线的报文跟网络报文完全不是一个思路。网络上是“点到点”的寻址CAN总线上是“广播仲裁”——所有节点挂在同一对双绞线上谁都可以发但同一时刻只允许一个节点占用总线。CAN标准帧的格式简化为帧起始位、仲裁场11位识别符加RTR位、控制场IDE位、DLC数据长度代码、数据场最多8字节、CRC场15位、应答场、帧结束。这当中仲裁场最关键两个节点同时发送时识别符数值小的帧享有更高优先级自动“抢到”总线。用CANoe解析CAN报文时你看到的通常不是裸十六进制而是经过数据库文件DBC翻译后的物理量。比如收到一帧CAN ID为0x18FF50E5的报文DBC文件里定义了字节0到字节3是发动机转速字节4到字节7是冷却液温度CANoe直接标度变换成转速7500rpm、温度87℃。但要追踪疑难杂症必须回到原始字节流去看因为DBC翻译是“按设计者预期”翻译的数据异常时往往恰恰是某个信号超出了预期范围。CANoe里录完整报文有讲究默认的Trace窗口只显示当前在线解析的帧一旦过滤条件没设对数据就丢了。正确的做法是在Measurement Setup里拖一个Logging模块配置成保存为BLF或ASC格式记录所有总线上出现的帧。之后再回放把复现故障时的数据与正常数据逐帧对比很多“偶发故障”就是在这样的对比里找到根因的。3.3 LIN诊断报文低速控制的低成本方案LIN总线常出现在车窗、后视镜、空调面板这类对速率要求不高的节点上它最大的特点是只需要一根线成本远低于CAN。LIN报文结构比较特别报文头总是由主机节点发送包含同步场和PID从机节点收到后按PID判断这帧是否跟自己有关然后再发送响应数据。诊断报文的PID通常固定走0x3C和0x3D一个用于主机请求一个用于从机应答。做LIN诊断解析时看到PID 0x3C别急着当普通数据帧处理它前面可能还有NAD节点地址和SID服务标识符等字段。很多新手把诊断报文的第一个字节当成数据结果把服务标识符都解析错了。3.4 MODBUS报文四个字节说清一件设备操作MODBUS在工控领域地位极高PLC、仪表、变频器几乎都支持。以MODBUS RTU为例报文格式里第一个字节是设备地址告诉总线“这帧是发给谁的”第二个字节是功能码代表要干什么比如03是读保持寄存器06是写单个寄存器10是写多个寄存器然后是数据字段和CRC16校验。实际读一个现场仪表的温度值请求报文往往是这样的十六进制序列01 03 00 00 00 01 84 0A01设备地址1号仪表03功能码“读保持寄存器”00 00寄存器起始地址000 01读取1个寄存器84 0A对前面6个字节算出的CRC16校验仪表回包就是01 03 02 02 1B 39 6A01 03设备地址和功能码原样返回02数据字节数后面两个字节是数据02 1B寄存器值十六进制0x021B转十进制是539再按量纲除以10温度就是53.9℃39 6A新CRC注意一个细节相同功能在MODBUS RTU和MODBUS TCP下字节流完全不同。TCP模式下MBAP头占7个字节替代了地址和CRC的校验位置还多了事务处理标识符用来关联请求与响应。排错时先搞清走的是RTU还是TCP否则对着报文套CRC验证逻辑怎么都对不上。3.5 电力规约报文固定帧头帧尾代表的是“强制秩序”电力行业用的IEC 60870-5-101遥控报文、水文SL651报文、以及国网698.45报文风格比工业总线还要“死板”因为电力系统不允许乱。101规约遥控报文典型结构里启动字符固定为0x68然后跟一个长度字节L之后是控制域C、地址域A、链路用户数据帧尾是结束字符0x16和校验码。遥控命令里78 01这种值代表“合闸指令”00 00 00这种代表“分闸指令”不同厂家的间隔时间、附加信息域设置会有所差异但帧的“骨架”必须按标准走解析时先把固定帧头匹配上再按偏移量处理后续字节。SL651水文规约和698.45电表规约的帧格式大同小异都是“帧头长度控制字地址数据校验帧尾”的套路。处理这一类报文最容易踩的坑是CRC校验算法有时是标准CRC16有时是自定义的多项式解析前必须先确认协议版本否则一个字节校验不过整个链路就像翻译错了一句话后面全乱。4. 抓包工具的门道Wireshark与CANoe的高效用法4.1 Wireshark的过滤语言写好了效率翻倍Wireshark真正强大的是过滤表达式。基本过滤直接输入icmp、tcp.port80、ip.src192.168.1.10但更推荐组合表达式。排HTTP接口超时先过滤http ip.addr192.168.2.100然后用“分析-追踪流-HTTP流”查看请求响应全貌。抓加密接口时直接搜HTTP协议是看不到内容的要在首部信息里按照Content-Type字段区分类型。如果遇到一条连接反复重传过滤出tcp.analysis.retransmission能看到重传的包全部标成黑色。重传数量一多基本可以断定TCP层出现丢包而不是应用层的问题——这时候要继续往下挖物理链路而不是改代码。注意在GNS3里做路由器互联分析时链路两端的路由器接的主机分别为IP 192.168.1.1和192.168.2.1中间路由器的接口要分别配置对应的网关。然后在这两台主机上抓包肉眼就能看到ARP广播请求、ARP应答以及最终的IP数据报文从一端进入路由器再从另一端出去的全过程。这个过程对理解“报文转发”帮助极大。4.2 CANoe录报文不是点了开始就万事大吉CANoe录注意事项先确认总线通道配置正确是CAN 250kbps、500kbps还是CAN FD日志文件格式建议选BLF索引速度快回放不卡顿Recording属性必须选“全部帧”不是“在线解析帧”如果要对比保持离线回放时的采样时间戳一致很多人录完发现LOG文件里只有几十帧大概率是Filter配置把非DBC信号帧过滤掉了。DBC的过滤适合调试特定信号不适合做完整报文记录存“原始帧”才是录完整报文的关键。4.3 明文报文和加密报文怎样跟安全打交道热搜词里有一项“报文加解密开发指引”。报文在互联网和对接场景里现在明文传输几乎绝迹了。金融、政务类接口的报文处理流程通常是先对报文体做Base64编码再用对称加密算法加密报文体最后用接收方公钥做非对称加密传输对称密钥——也就是“数字信封”。开发的时候习惯先把加解密步骤拆成函数逐层打印中间密文和明文先用一帧明文样本跑通全流程再做边界测试这样调试效率最高。需要明确的是你不能在网关上指望靠协议解析拿到明文内容加密报文的解析必须依赖业务系统提供的解密SDK抓包只能看到密文。所以“报文解析”和“报文解密”是两个完全不同的层次前者解决的是结构识别后者解决的是内容查看。5. 从异常报文中定位问题一条丢包链路的实证推演5.1 先判断问题层次物理层、链路层还是传输层有个常见场景Windows主机Ping网关丢包率超过30%。只看Ping结果你不知道包丢在哪一段。用Wireshark抓包的时候同时抓三层数据链路层的ARP请求和ARP应答是否完整出现网络层的IP报文是否有去无回传输层的TCP重传比例有多高如果ARP应答每次都出现说明二层链路正常如果ICMP请求全出去了但应答时有时无问题就可能出在目的主机或者中间三层设备上。如果连ARP请求都时有时无那就得往上查网卡驱动、双工模式或者物理链路协商结果——百兆网口强制全双工而交换机是半双工时冲突丢包的现象很容易被误判成线缆问题。5.2 用IO图验证丢包的核心步骤打开Wireshark统计菜单添加两条过滤器的IO图一条是icmp.type8一条是icmp.type0。时间粒度选0.5秒。然后同时开两个持续Ping一个发大包1400字节一个发小包32字节。如果小包两条曲线几乎重合大包请求曲线远高于应答曲线那大概率是中间链路的MTU问题——大包被分片、丢弃或者中间设备禁用了分片。接着用Ping带DF位的命令测一下ping 目标IP -f -l 1472收到“需要拆分数据包但是设置DF”的提示就能把问题极其精准地锁到MTU上。这也是报文分析实战里最典型的“丢包率误判”场景Ping默认小包能通业务大包全断。5.3 从ARP到IP转发的完整链路观察热搜里有一条关于GNS3、两个路由器连接主机然后分析IP数据转发报文和ARP协议的内容。这个实验做得好的话几乎能把报文的转发全过程看完整。主机A192.168.1.10Ping主机B192.168.2.10时第一帧是ARP广播请求询问“谁是192.168.1.1”这是为了让A知道网关的MAC地址。路由器R1回一个ARP应答A就把R1的MAC记在ARP缓存里。随后A发出IP报文目的MAC填R1的接口MAC源MAC填A自己目的IP是192.168.2.10。R1收到后发现目的IP不在自己网段就查路由表找到去往192.168.2.0/24的下一跳是R2。R1为了把帧发往R2要先在自己的出口接口上解析R2对应接口的MAC地址于是又出现一次ARP。帧从R1到R2目的MAC变成R2的接口MAC源MAC变成R1出口的MAC但IP层的源IP和目的IP始终未变。这时候你再回看Wireshark的报文列表每一跳的源目MAC都在变而源目IP一直不变。这就是“报文在每一跳被重新封装”的最直观证据。看懂了这一段什么三层转发、二层交换、VLAN间路由全都串起来了。6. 报文解析的几条心法写在最后的大白话经验6.1 先找边界再做翻译不管拿到的是什么协议的报文第一件事永远是找帧头和帧尾。网络协议看IP首部固定字段CAN总线看帧起始位和EOFMODBUS看地址字和CRC电力规约看0x68启动字符和0x16结束字符。边界确定不了后续一切解析都是瞎猜。有一个项目里对方给的“自定义报文”文档写得很模糊数据区究竟是32位无符号还是16位有符号全靠猜。我最后是拿了十组真实样本逐字节推算变化规律才反推出来数据是用小端存储的两个16位字段。这件事给我的教训是报文解析顺序应当是“抓样本、找特征、套规范、验逻辑”而不是一上来就期望规范文档面面俱到。6.2 校验字段永远是第一道筛子CRC校验过不了别急着往后看数据。很大概率是抓包丢帧或者字节序标错了。大多数字节序问题通过交换高低字节就能解决。校验通过后再去分析字段含义你会省掉大量时间。6.3 十六进制和ASCII同步看Wireshark和CANoe这类工具都有同步显示十六进制和ASCII的窗口。报文里的可见字符会在ASCII栏直接显示出来能快速判断出哪些是协议数据、哪些是负载内容。某些明文协议里厂家会把设备型号、固件版本直接塞进数据区用ASCII视图一眼就能扫出来。6.4 拿参考报文对答案做协议对接时第一步不是写解析代码而是找一套参考报文样本。协议文档可能写得有歧义但样本不会骗人。先拿样本对着文档逐字段过一遍确认每个字节的含义和边界再动手写代码。这样做出来的解析器基本不会在联调时翻车。报文这东西说穿了就是双方约定好的一种“对话格式”。格式本身不神秘神秘的是数据里藏着的设备状态和链路状态。多用工具去抓、去拆、去对比几套协议啃下来你就能从任何一串十六进制里读出故事情节来。