Modbus Server与Client寄存器读写不一致问题求助
Modbus Server/Client 通信异常问题解决
问题现象
在Ubuntu虚拟机中模拟Modbus通信时,出现以下异常:
- Server持续向寄存器0写入随机值,但Client首次读取时只能得到初始值
0,无法获取Server写入的随机值。 - Client向寄存器0写入值后,后续运行只能读取到自身写入的值,无法获取Server持续更新的新值。
原代码及输出
Server代码
import random from pyModbusTCP.server import ModbusServer, DataBank from time import sleep #instance of ModbusServer server = ModbusServer("127.0.0.1", 12344, no_block=True) #instance of DataBank data_bank = DataBank() server.data_bank = data_bank try: print("Start Server...") server.start() print("Server is online") state = 0 while True: data_bank.set_holding_registers(0, [random.randint(1, 100)]) # Set holding register values if state != data_bank.get_holding_registers(0, 1)[0]: # Get holding register values state = data_bank.get_holding_registers(0, 1)[0] print("Value of Register 1 has changed to " + str(state)) sleep(1) except Exception as e: print(f"An error occurred: {e}") print("Shutdown server...") server.stop() print("Server is stopped")
Server输出
Start Server... Server is online Value of Register 1 has changed to 88 Value of Register 1 has changed to 83 Value of Register 1 has changed to 51 Value of Register 1 has changed to 61 Value of Register 1 has changed to 45 ^CTraceback (most recent call last): File "/home/neptun/Desktop/modbusyt/server.py", line 22, in <module> sleep(1) KeyboardInterrupt
Client代码
import pyModbusTCP from pyModbusTCP.client import ModbusClient client = ModbusClient(host='127.0.0.1', port=12344, auto_open=True, debug=False) try: regs = client.read_holding_registers(0, 1) if regs: print(regs) else: print("Read error") except pyModbusTCP.ModbusIOException as e: print(f"Error reading registers: {e}") try: client.write_multiple_registers(0, [1, 2, 3]) regs = client.read_holding_registers(0, 5) if regs: print(regs) else: print("Read error") except pyModbusTCP.ModbusIOException as e: print(f"Error writing registers: {e}")
Client输出
# first run: [0] [1, 2, 3, 0, 0] # Consecutive runs: [1] [1, 2, 3, 0, 0]
问题根源
- Server CPU占用过高:原Server代码中仅在寄存器值变化时执行
sleep(1),若随机值重复会导致无限循环,占用100%CPU,使得Modbus服务线程无法及时处理客户端请求。 - 读取时机不合理:Client首次读取时,可能在Server完成第一次寄存器写入前就发起请求,导致读到初始值
0。 - 线程同步隐患:自定义DataBank实例后,主线程与服务线程的寄存器操作可能存在同步问题。
修复方案
修改后的Server代码
import random from pyModbusTCP.server import ModbusServer from time import sleep # 初始化Modbus服务器 server = ModbusServer("127.0.0.1", 12344, no_block=True) try: print("启动服务器...") server.start() print("服务器已上线") state = 0 while True: # 生成随机值并写入寄存器0 new_val = random.randint(1, 100) server.data_bank.set_holding_registers(0, [new_val]) # 仅当值变化时打印日志 if state != new_val: state = new_val print(f"寄存器0的值已变更为 {state}") # 固定每秒更新一次,避免CPU占用过高 sleep(1) except Exception as e: print(f"发生错误: {e}") print("正在关闭服务器...") server.stop() print("服务器已停止")
修改后的Client代码
from pyModbusTCP.client import ModbusClient from time import sleep # 初始化客户端,手动控制连接 client = ModbusClient(host='127.0.0.1', port=12344, auto_open=False, debug=False) # 尝试连接服务器 if not client.open(): print("无法连接到Modbus服务器") exit() try: # 等待服务器完成初始写入,确保读取到有效数据 sleep(0.5) # 读取寄存器0的值 regs = client.read_holding_registers(0, 1) if regs: print(f"读取寄存器0的值: {regs}") else: print("读取寄存器0失败") except Exception as e: print(f"读取错误: {e}") try: # 向寄存器0、1、2写入值1、2、3 if client.write_multiple_registers(0, [1, 2, 3]): print("写入寄存器成功") # 读取寄存器0-4的值 regs = client.read_holding_registers(0, 5) if regs: print(f"读取寄存器0-4的值: {regs}") else: print("读取寄存器0-4失败") else: print("写入寄存器失败") except Exception as e: print(f"写入错误: {e}") # 关闭客户端连接 client.close()
修复说明
Server端:
- 将
sleep(1)移到循环末尾,固定每秒更新一次寄存器,彻底解决CPU占用过高问题,保证服务线程正常响应客户端请求。 - 直接使用服务器自带的
data_bank,避免自定义实例的关联隐患。 - 提前生成随机值,减少重复读取寄存器的开销。
- 将
Client端:
- 手动控制连接流程,增加连接失败的判断逻辑。
- 增加短暂延迟,确保服务器完成初始写入后再读取,避免首次读到初始值
0。 - 增加写入操作的结果判断,便于排查问题。
内容的提问来源于stack exchange,提问作者Shivansh Sharma
相关产品推荐
相关产品推荐

