Modbus单元标识与广播:TCP请求如何路由到RTU总线
TCP连接只能选中网关,未必选中了网关后面的仪表。MBAP中的单元标识Unit Identifier承担路由信息,但它的含义取决于目标类型。常见错误是把它当作通用站号:网关正确发出了串口广播,随后又因等不到任何仪表回复而报超时,甚至自动重发同一写命令。
本文依据Modbus应用协议V1.1b3、串行链路规范V1.02及TCP实现指南V1.0b。下面的路由策略和验收步骤属于建议方案,没有对特定网关进行硬件实测;厂商自定义映射仍须查阅对应产品与固件文档。

先分清网络端点与下游地址
把目标记录为一组字段:网关IP、TCP端口、串口总线段、单元标识和功能码。两个独立串口段都可以存在站号七,它们并不是同一台设备。因此,必须先由配置确定总线段,串口站号才有完整含义。不要只在日志里写“访问设备七”。
TCP实现指南第3.1.3及4.4.1节说明,单元标识位于MBAP头中,可供网关选择后端设备。对于直接接入TCP网络的服务器,指南建议使用不具下游路由意义的0xFF,同时允许零。因此,原生TCP设备收到单元标识零,并不自动意味着串口广播,必须先确认端点角色。
把映射写出来,并拒绝歧义
简单桥接可以把单元标识七映射为指定串口上的RTU站号七;复杂产品可能另有路由表。诊断记录应同时保留输入标识、输出端口、实际站号和配置版本。路由配置改过之后,旧抓包仍要能按当时的配置解释。
串行规范第2.1至2.2节规定,单播站号为一至二百四十七,零用于广播,其余高位地址保留。不要因为上位机默认使用二百五十五,就把它原样当作正常串口站号。没有匹配路由时,也不要偷偷选择第一台设备。更安全的实现是按产品契约在本地拒绝,并保证串口没有发出请求。
把广播作为独立授权能力
串口广播针对所有参与设备执行写操作,设备不返回响应。向零地址发送读请求,不会得到可合并的多设备读数。验证广播功能时应使用模拟器,或明确批准、与生产隔离的测试段,并选择没有危险副作用的写入对象。
广播白名单至少覆盖总线段、功能码和寄存器范围。混合设备可能把同一偏移定义为完全不同的设置,因此格式正确仍可能造成业务错误。设备清单或寄存器兼容性不明确时,应关闭广播。允许客户端单播写某一台仪表,不代表允许它一次修改整条总线。
说明TCP调用方会看见什么
串行规范定义了从站不回复,但没有让网关自行生成的TCP确认具备“所有设备执行成功”的含义。不同网关可能直接拒绝广播、提供专用接口,或返回本地产生的结果。接入前必须写清当前产品采用哪种行为,并标注结果来自网关还是设备。
建议区分“已进入网关队列”“串口发送完成”“设备状态已验证”。TCP发送接口返回成功,不能证明后两项。如果客户端库坚持每次请求都要有正常响应,应先验证它与网关广播契约兼容。否则,无响应这一正常行为会触发通用重试,导致命令被反复执行。
周转等待不是响应超时
广播发出后,主站仍需等待周转时间,让从站处理完命令再接受下一次请求。这与单播等待回复属于不同状态,见串行规范第2.4节主站状态模型。等待长度应依据具体设备和操作要求设置,不能直接套用TCP网络时延。
调度器应走广播专用完成路径,再遵守配置的周转时间。也不要把它等同于RTU帧间隔:前者考虑设备处理就绪,后者用于区分帧边界。配置表应单独列出这两个参数,避免维护人员把它们合成一个“延时”。
用边界输入验证路由
建立包含两个模拟总线段的夹具,为每段配置已知站号。对受支持路由发出安全单播读请求,同时记录TCP标识、选定端口和串口帧中的地址。对未知标识,验收重点是串口完全没有输出。测试值应覆盖零、一、二百四十七、二百四十八和二百五十五,不能只验证一个普通地址。
在隔离的广播夹具中执行批准的写操作,确认网关不会因缺少从站响应而进入单播超时或重试路径。随后安排单播读,检查周转后调度是否恢复。各模拟从站的状态应分别观察,不能把“总线安静”当作每台设备都收到并执行的证据。
交付可审核的路由契约
- 每组端点和单元标识都对应明确总线段、站号或拒绝结果。
- 原生TCP特殊值与串口保留地址按各自语境处理。
- 广播授权范围、允许写入、结果来源和重试行为对调用方可见。
- 周转等待与单播响应期限分别配置。
- 未知路由和禁止广播不会产生下游副作用。
把路由表、网关固件版本、客户端参数和夹具抓包一起保存,才能解释网关承诺了什么、实际转发了什么。这些证据不能证明每个广播接收方都完成了动作;后者还需要设备专用观察点及应用层验证方案。