4. Modbus协议详解(下):Modbus TCP协议、RTU与TCP的差异、实际报文抓包分析

好,咱们接着往下聊。上一节我们把Modbus RTU的底裤都扒干净了,从物理层到报文结构,再到那个让人又爱又恨的CRC校验。这一节,咱们把目光转向工业以太网——Modbus TCP。

说实话,我最早接触Modbus TCP是在一个光伏电站的监控项目里。那时候现场有几十台逆变器,距离远、节点多,用RS485组网简直要命。后来换成以太网,整个世界都清净了。你想想看,一根网线就能搞定通信,还能顺便上网,多爽。

4.1 Modbus TCP协议栈

Modbus TCP,说白了就是把Modbus的报文装进TCP/IP的壳子里。它工作在OSI模型的第七层——应用层。底层依赖TCP协议保证可靠传输。

为什么选TCP而不是UDP?我个人的理解是:工业现场环境复杂,丢包重传是家常便饭。TCP的确认重传机制,能保证数据不丢不乱。虽然牺牲了一点实时性,但换来的是可靠性。嗯,在能源物联网里,可靠性比实时性重要得多。

核心要点:Modbus TCP = Modbus应用协议 + TCP/IP传输。端口号固定为502。

这里有个细节很多人会忽略:Modbus TCP的报文里,没有CRC校验。为什么?因为TCP/IP协议栈底层已经做了校验和,再搞CRC就是脱裤子放屁。我在给客户做培训时,经常有人问这个问题,今天一并讲清楚。

4.2 Modbus TCP报文结构

咱们直接看报文格式。Modbus TCP的报文比RTU简单得多,它去掉了地址域和CRC,取而代之的是MBAP报文头。

字段 长度(字节) 说明
事务处理标识符 2 用于匹配请求和响应,一般从0开始递增
协议标识符 2 固定为0x0000,表示Modbus协议
长度 2 后续字节数(从单元标识符开始算起)
单元标识符 1 相当于RTU的从站地址,用于网关路由
功能码 1 与RTU完全一致
数据 N 与RTU完全一致

你看,MBAP头一共7个字节,加上功能码和数据,就是完整的Modbus TCP报文。相比RTU,少了地址域(1字节)和CRC(2字节),多了MBAP头(7字节)。

实战技巧:事务处理标识符怎么用?我习惯的做法是:客户端每发一个请求,标识符加1。服务器响应时必须原样返回这个标识符。这样客户端就能知道哪个响应对应哪个请求。尤其是在并发请求时,这个字段就是救命稻草。

4.3 RTU与TCP的差异对比

咱们用一张表把差异说清楚。我当年做技术选型时,就是靠这张表说服了项目经理改用TCP。

对比项 Modbus RTU Modbus TCP
物理层 RS232/RS485 以太网(RJ45、光纤)
传输方式 半双工 全双工
最大节点数 32(RS485无中继) 理论无限制
通信距离 1200米(RS485) 100米(网线),可扩展
报文头 地址域(1字节) MBAP头(7字节)
校验方式 CRC16 TCP校验和
从站地址 必须,1-247 可选,通过单元标识符
典型应用 小规模、短距离 大规模、远程监控

这里有个坑,我曾经踩过:RTU转TCP网关。很多网关默认把RTU的从站地址映射到TCP的单元标识符。但有些设备不按套路出牌,单元标识符固定填0xFF。结果就是,网关不知道数据该发给谁。嗯,遇到这种情况,我一般建议在网关里做静态路由表。

4.4 实际报文抓包分析

光说不练假把式。咱们用Wireshark抓个包,看看Modbus TCP到底长什么样。

假设我们要读取从站地址为1的设备的保持寄存器,起始地址0,读取2个寄存器。功能码是0x03。

请求报文(客户端→服务器):

事务标识符: 0x0001
协议标识符: 0x0000
长度:       0x0006
单元标识符: 0x01
功能码:     0x03
起始地址:   0x0000
寄存器数量: 0x0002

你看,长度字段是0x0006,表示从单元标识符开始到报文结束一共6个字节(1+1+2+2=6)。这个长度不包括MBAP头本身。

响应报文(服务器→客户端):

事务标识符: 0x0001
协议标识符: 0x0000
长度:       0x0007
单元标识符: 0x01
功能码:     0x03
数据长度:   0x04
数据:       0x1234 0x5678

响应里多了个数据长度字段,告诉客户端后面跟了多少字节的数据。这里是4个字节,对应2个寄存器(每个寄存器2字节)。

注意:Wireshark抓包时,如果看到协议标识符不是0x0000,那大概率不是标准的Modbus TCP。有些厂家会魔改协议,比如把协议标识符改成自己的厂商标识。遇到这种情况,我建议直接找厂家要协议文档,别自己瞎猜。

4.5 抓包实战中的常见问题

我总结几个抓包时经常遇到的问题,都是血泪教训:

  • 报文不完整:Wireshark有时会把一个Modbus TCP报文拆成多个TCP段。别慌,Wireshark会自动重组,你只需要在过滤栏输入modbus就行。
  • 响应超时:如果发了请求没收到响应,先检查端口是不是502。有些设备默认端口不是502,需要手动配置。
  • 事务标识符不匹配:响应的事务标识符必须和请求一致。如果不一致,说明服务器实现有问题。我曾经遇到过一台逆变器,事务标识符永远返回0x0000,气得我直接找厂家要固件补丁。

我的习惯:抓包时,我会同时抓客户端和服务器的网卡。这样能确认报文到底是在哪一端丢的。如果是客户端发了但服务器没收到,那就是网络问题;如果服务器回了但客户端没收到,那就是防火墙或路由问题。

4.6 知识体系总览

为了让你对本章内容有个整体把握,我画了一张图。这张图把Modbus TCP的核心知识点串起来了。

Modbus TCP 知识体系 Modbus TCP 协议栈:应用层 报文结构:MBAP头 与RTU差异对比 TCP/IP底层:端口502 可靠传输:确认重传 事务标识符:匹配请求响应 无CRC:依赖TCP校验 物理层:以太网 vs 串口 通信方式:全双工 vs 半双工 实际报文抓包分析 请求报文:功能码+数据 响应报文:数据长度+数据 常见问题:超时/不匹配

这张图把Modbus TCP的核心知识点分成了三大块:协议栈、报文结构、与RTU的差异。底部是抓包分析,这是咱们实战中最常用的技能。你想想看,掌握了这些,以后在光伏储能项目里,不管是调试逆变器还是BMS,心里都有底了。

好了,这一节的内容就到这儿。Modbus TCP其实不难,关键是理解它和RTU的差异,以及学会用Wireshark抓包分析。下一节咱们聊聊Modbus的高级应用,包括多主站通信和网关配置,那才是真正考验功力的时候。


公众号:蓝海资料掘金营,微信deep3321