3. Modbus TCP服务器模拟
任务目标
实现一个基于Node.js的Modbus TCP服务器,模拟从站设备(Slave),能够响应标准Modbus TCP功能码请求(读保持寄存器0x03、写单个寄存器0x06、写多个寄存器0x10),用于在无真实硬件时测试Modbus主站(客户端)程序。
环境依赖
需要Node.js 14+环境,安装modbus-serial库(同时作为服务器和后续测试客户端)。
npm install modbus-serial
关键完整代码
以下代码创建了一个Modbus TCP服务器,监听端口8502,内部维护一个长度为10的保持寄存器数组(地址0~9),并实现读写请求的响应逻辑。
// modbus-tcp-server.js
const ModbusRTU = require("modbus-serial");
// 模拟从站数据区:保持寄存器(地址0~9)
const holdingRegisters = new Array(10).fill(0);
holdingRegisters[0] = 100; // 设备状态
holdingRegisters[1] = 200; // 运行参数
// 创建TCP服务器,绑定端口8502
const server = new ModbusRTU.ServerTCP({
port: 8502,
debug: false,
unitID: 1, // 从站单元标识符
holdingRegister: holdingRegisters
});
// 监听服务器启动事件
server.on("initialized", () => {
console.log("Modbus TCP 服务器已启动: 端口 8502, 单元ID=1");
console.log("保持寄存器初始值:", holdingRegisters);
});
// 监听错误事件
server.on("error", (err) => {
console.error("服务器错误:", err.message);
});
// 可选:监听请求日志(便于调试)
server.on("debug", (msg) => {
console.log("请求日志:", msg);
});
运行与验证方法
启动服务器:
node modbus-tcp-server.js
看到控制台输出“服务器已启动”即表示监听成功。
验证读写功能(使用同一库作为客户端测试):
新建文件test-client.js,内容如下:
// test-client.js
const ModbusRTU = require("modbus-serial");
async function test() {
const client = new ModbusRTU();
await client.connectTCP("127.0.0.1", { port: 8502 });
client.setID(1);
// 1. 读保持寄存器(功能码0x03):读取地址0~2,共3个寄存器
const readRes = await client.readHoldingRegisters(0, 3);
console.log("读取结果:", readRes.data); // 预期输出: [ 100, 200, 0 ]
// 2. 写单个寄存器(功能码0x06):将地址2的值写为 300
await client.writeRegister(2, 300);
const readAfterSingle = await client.readHoldingRegisters(2, 1);
console.log("写单个后读取:", readAfterSingle.data); // 预期输出: [ 300 ]
// 3. 写多个寄存器(功能码0x10):从地址3开始写入 [1, 2, 3]
await client.writeRegisters(3, [1, 2, 3]);
const readAfterMulti = await client.readHoldingRegisters(3, 3);
console.log("写多个后读取:", readAfterMulti.data); // 预期输出: [ 1, 2, 3 ]
client.close();
console.log("测试完成");
}
test().catch(console.error);
运行测试客户端:
node test-client.js
通过条件:客户端控制台依次输出以下三行结果,即表示服务器正确响应了三种读写请求:
读取结果: [ 100, 200, 0 ]
写单个后读取: [ 300 ]
写多个后读取: [ 1, 2, 3 ]
常见问题
- 端口被占用:若8502被占用,修改代码中
port值并同步修改客户端连接端口。 - 连接失败:确认服务器已启动且客户端连接IP/端口一致;若跨设备测试,需将IP改为服务器实际IP并确保防火墙放行。
- 寄存器地址越界:当前仅支持地址0~9,读写超出范围会返回异常码
0x02(非法数据地址),属正常Modbus协议行为。