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的核心知识点分成了三大块:协议栈、报文结构、与RTU的差异。底部是抓包分析,这是咱们实战中最常用的技能。你想想看,掌握了这些,以后在光伏储能项目里,不管是调试逆变器还是BMS,心里都有底了。
好了,这一节的内容就到这儿。Modbus TCP其实不难,关键是理解它和RTU的差异,以及学会用Wireshark抓包分析。下一节咱们聊聊Modbus的高级应用,包括多主站通信和网关配置,那才是真正考验功力的时候。
公众号:蓝海资料掘金营,微信deep3321