如何用pyModbusTCP在同一程序中实现多Slave ID的TCP服务器?
单Python程序实现多Slave ID的Modbus TCP模拟器方案
核心结论
两种方案中,单个服务器实例处理多Slave ID是最优解,同一IP同端口无法启动多个服务器实例(TCP协议不允许端口重复绑定),若强行用不同端口则不符合你模拟RTU转TCP网关的需求。
方案一:单个服务器实例处理多Slave ID
这是最贴合你需求的实现方式,无需启动多个服务器,只需在一个服务器内为每个Slave ID维护独立的寄存器空间,完全模拟RTU转TCP网关的行为。
实现思路
- 基于
pymodbus这类主流Modbus库扩展,在请求处理阶段根据slave_id(即Unit ID)将读写操作路由到对应Slave的寄存器集合。 - 每个Slave ID对应一套独立的线圈、离散输入、保持寄存器、输入寄存器。
代码示例(基于pymodbus)
from pymodbus.server import StartTcpServer from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext # 为Slave ID 1创建独立寄存器上下文 slave_1_ctx = ModbusSlaveContext( di=None, co=None, hr=None, ir=None, # 按需初始化对应类型寄存器 zero_mode=True ) # 为Slave ID 2创建独立寄存器上下文 slave_2_ctx = ModbusSlaveContext( di=None, co=None, hr=None, ir=None, zero_mode=True ) # 构建服务器上下文,映射Slave ID到对应寄存器空间 server_context = ModbusServerContext(slaves={1: slave_1_ctx, 2: slave_2_ctx}, single=False) # 启动TCP服务器,监听localhost的5020端口 StartTcpServer(context=server_context, address=("localhost", 5020))
关键说明
single=False明确告知服务器支持多Slave ID模式,每个ID对应独立的寄存器空间。- 客户端发起读写请求时,指定的Slave ID会被服务器识别,自动路由到对应寄存器集合处理,完全符合Modbus TCP协议规范。
方案二:同一程序启动多个服务器实例(不推荐)
你之前的怀疑是正确的:同一IP的同一端口无法绑定多个服务器实例,TCP协议不允许端口重复占用。如果非要启动多个实例,只能为每个服务器分配不同端口,但这与你模拟同网关下多设备的需求不符(实际RTU转TCP网关是所有设备共用一个TCP端口,靠Slave ID区分)。
若仅用于测试不同端口的设备,代码示例如下:
import threading from pymodbus.server import StartTcpServer from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext def start_server(port, slave_id): slave_ctx = ModbusSlaveContext(zero_mode=True) server_ctx = ModbusServerContext(slaves={slave_id: slave_ctx}, single=True) StartTcpServer(context=server_ctx, address=("localhost", port)) # 启动两个不同端口的服务器实例 threading.Thread(target=start_server, args=(5020, 1)).start() threading.Thread(target=start_server, args=(5021, 2)).start()
总结
优先选择方案一,它完全匹配你模拟RTU转TCP网关、单程序单端口多Slave ID的需求,实现简单且符合协议规范。
内容的提问来源于stack exchange,提问作者mg3
相关产品推荐
相关产品推荐

