基于 C# 和 NModbus 库的 Modbus TCP 通信示例源码,包含 客户端(Master) 和 服务器端(Slave) 的实现,支持读写寄存器、线圈等操作。
一、环境准备
-
NuGet 依赖安装
在项目中安装
NModbus库(支持 .NET Framework 和 .NET Core):Install-Package NModbus -
网络配置 Modbus TCP 默认端口为 502,需确保防火墙开放该端口。 从站地址(Unit ID)范围:1~247(默认 1)。
二、Modbus TCP 客户端(Master)示例
1. 同步读写操作
using System;
using System.Net.Sockets;
using Modbus.Device;class ModbusTcpClientDemo
{static void Main(){string ipAddress = "192.168.1.100"; // 从站 IPint port = 502; // Modbus TCP 端口ushort unitId = 1; // 从站地址using (TcpClient client = new TcpClient(ipAddress, port)){ModbusTcpMaster master = ModbusTcpMaster.CreateIp(client);try{// 读取保持寄存器(地址0,长度10)ushort startAddr = 0;ushort numRegs = 10;ushort[] registers = master.ReadHoldingRegisters(unitId, startAddr, numRegs);Console.WriteLine("读取保持寄存器结果:");for (int i = 0; i < registers.Length; i++){Console.WriteLine($"地址 {startAddr + i}: {registers[i]}");}// 写入单个寄存器(地址0,值1234)ushort writeAddr = 0;ushort writeValue = 1234;master.WriteSingleRegister(unitId, writeAddr, writeValue);Console.WriteLine($"写入寄存器 {writeAddr} 成功,值为 {writeValue}");}catch (Exception ex){Console.WriteLine($"通信错误:{ex.Message}");}}}
}
2. 异步读写操作
using System;
using System.Net.Sockets;
using Modbus.Device;
using System.Threading.Tasks;class ModbusTcpAsyncDemo
{static async Task Main(){string ipAddress = "192.168.1.100";int port = 502;ushort unitId = 1;using (TcpClient client = new TcpClient()){await client.ConnectAsync(ipAddress, port);ModbusTcpMaster master = ModbusTcpMaster.CreateIp(client);try{// 异步读取保持寄存器ushort startAddr = 0;ushort numRegs = 10;ushort[] registers = await master.ReadHoldingRegistersAsync(unitId, startAddr, numRegs);Console.WriteLine("异步读取结果:");foreach (var reg in registers){Console.Write(reg + " ");}// 异步写入多个线圈ushort startCoil = 0;bool[] coilValues = { true, false, true };await master.WriteCoilsAsync(unitId, startCoil, coilValues);}catch (Exception ex){Console.WriteLine($"异步通信错误:{ex.Message}");}finally{client.Close();}}}
}
三、Modbus TCP 服务器端(Slave)示例
1. 基础服务器实现
using System;
using System.Net;
using System.Net.Sockets;
using Modbus.Device;
using Modbus.Utility;class ModbusTcpSlaveDemo
{static void Main(){ushort slaveId = 1; // 从站 IDint port = 502; // 监听端口using (TcpListener listener = new TcpListener(IPAddress.Any, port)){listener.Start();Console.WriteLine($"Modbus TCP 从站已启动,监听端口 {port}...");ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveId, listener);slave.DataStore = DataStoreFactory.CreateDefaultDataStore(); // 初始化数据存储// 模拟数据更新(例如传感器数据)System.Timers.Timer timer = new System.Timers.Timer(1000);timer.Elapsed += (s, e) =>{ushort[] holdingRegs = slave.DataStore.HoldingRegisters;for (int i = 0; i < holdingRegs.Length; i++){holdingRegs[i] = (ushort)(i + (int)(DateTime.Now.Second * 0.5)); // 动态数据}};timer.Start();slave.Listen(); // 开始监听请求Console.WriteLine("按任意键退出...");Console.ReadKey();slave.Stop();}}
}
2. 自定义数据处理(事件驱动)
using System;
using Modbus.Device;
using Modbus.Utility;class CustomModbusSlave
{public static void Main(){ushort slaveId = 1;int port = 502;using (TcpListener listener = new TcpListener(IPAddress.Any, port)){listener.Start();ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveId, listener);slave.DataStore = DataStoreFactory.CreateDefaultDataStore();// 注册事件处理slave.ModbusSlaveRequestReceived += (sender, e) =>{Console.WriteLine($"收到请求:功能码 {e.Message.FunctionCode},地址 {e.Message.StartAddress},长度 {e.Message.Quantity}");};slave.Listen();Console.WriteLine("自定义从站运行中,按任意键退出...");Console.ReadKey();slave.Stop();}}
}
参考代码 modbus tcp通讯 示例源码 www.youwenfan.com/contentcnn/93804.html
四、关键功能说明
- 数据存储区 保持寄存器(Holding Registers):地址从 0 开始,用于存储可读写的 16 位数据(如传感器值)。 输入寄存器(Input Registers):地址从 0 开始,仅支持读取(如设备状态)。 线圈(Coils):布尔值(0/1),地址从 0 开始。 离散输入(Discrete Inputs):只读布尔值。
- 异常处理 捕获
ModbusSlaveException处理协议错误(如非法地址)。 设置超时时间:master.Transport.ReadTimeout = 3000;(单位:毫秒)。 - 性能优化 批量读写:使用
ReadMultipleRegisters和WriteMultipleRegisters减少网络开销。 多线程处理:服务器端使用异步监听(async/await)提升并发能力。
五、测试工具推荐
- Modbus Poll(Windows) 功能:模拟主站,发送读写请求,验证从站响应。 下载地址:Modbus Poll /www.modbusdriver.com/software/modbus-poll.html)
- Modbus Slave(Windows) 功能:模拟从站,提供数据存储和响应。