C# 实现 Modbus TCP 通信
C# 实现 Modbus TCP 通信 结合主流开源库与底层协议实现
一、核心实现方案
1. 使用 NModbus 库(推荐)
安装依赖:
Install-Package NModbus # NuGet 安装
客户端代码示例:
using System.Net.Sockets;
using Modbus.Device;public class ModbusTcpClient
{public static void Main(){using TcpClient client = new TcpClient("192.168.0.100", 502); // 连接设备var master = ModbusTcpMaster.CreateIp(client); // 创建 Modbus 主机实例// 读取保持寄存器(地址0开始的10个寄存器)ushort[] registers = master.ReadHoldingRegisters(0, 10); foreach (var reg in registers){Console.WriteLine($"寄存器值: {reg}");}client.Close(); // 关闭连接}
}
关键点:
ReadHoldingRegisters():读取保持寄存器(功能码 0x03)WriteSingleRegister():写入单个寄存器(功能码 0x06)- 自动处理 MBAP 报文头(事务ID、协议ID等)
2. 手动实现协议帧(理解底层)
请求帧结构:
| 字段 | 事务ID (2B) | 协议ID (2B) | 长度 (2B) | 单元ID (1B) | 功能码 (1B) | 数据 (N B) |
|---|---|---|---|---|---|---|
| 示例 | 0x00 0x01 | 0x00 0x00 | 0x00 0x06 | 0x01 | 0x03 | 起始地址+数量 |
代码实现:
// 构建读寄存器请求帧 (功能码 0x03)
byte[] BuildReadRequest(ushort startAddr, ushort count)
{byte[] frame = new byte[12];// MBAP 头frame[0] = 0x00; frame[1] = 0x01; // 事务IDframe[4] = 0x00; frame[5] = 0x06; // 长度 = 6字节frame[6] = 0x01; // 单元ID// PDU 部分frame[7] = 0x03; // 功能码frame[8] = (byte)(startAddr >> 8); // 起始地址高字节frame[9] = (byte)startAddr; // 起始地址低字节frame[10] = (byte)(count >> 8); // 寄存器数量高字节frame[11] = (byte)count; // 寄存器数量低字节return frame;
}// 发送请求并解析响应
TcpClient client = new TcpClient("127.0.0.1", 502);
NetworkStream stream = client.GetStream();
stream.Write(requestFrame, 0, requestFrame.Length);byte[] response = new byte[256];
int bytesRead = stream.Read(response, 0, response.Length);
// 解析响应数据(略)
优势:深入理解协议细节,适合定制化场景。
二、进阶功能
1. 服务端实现(模拟设备)
using NModbus;
using NModbus.Tcp;var listener = new TcpListener(IPAddress.Any, 502);
listener.Start();
while (true)
{TcpClient client = listener.AcceptTcpClient();var factory = new ModbusFactory();var slave = factory.CreateSlave(1); // 从站地址=1// 绑定寄存器数据存储区slave.DataStore = new ModbusDataStore(); slave.DataStore.HoldingRegisters[0] = 1234; // 初始化寄存器值Task.Run(() => slave.Listen(client.GetStream())); // 异步处理请求
}
应用场景:设备仿真、测试上位机逻辑。
2. 错误处理与重连
try
{master.WriteSingleRegister(0, 100); // 写入寄存器
}
catch (SocketException ex)
{Console.WriteLine($"网络错误: {ex.Message}");Reconnect(client); // 重连逻辑
}
catch (ModbusException ex)
{Console.WriteLine($"Modbus错误码: {ex.ErrorCode}");
}
3. 批量操作优化
// 一次读取多个寄存器(减少请求次数)
ushort[] batchData = master.ReadHoldingRegisters(0, 50);// 批量写入寄存器
master.WriteMultipleRegisters(0, new ushort[]{10, 20, 30});
四、扩展应用
-
多设备管理
使用
Dictionary<string, TcpClient>管理多个设备连接。 -
安全通信
通过 VPN 或 TLS 加密隧道(需设备支持)。
-
与工业系统集成
- 读取 PLC 数据(如西门子 S7-1200)
- 连接 SCADA 系统(如 Ignition、WinCC)。
🔗 五、资源推荐
- 源码推荐:
- TCP Modbus通讯 采用TCP/IP通讯 www.youwenfan.com/contentcsj/112098.html
- 调试工具:
- Modbus Poll(测试客户端)
- Wireshark(抓包分析协议帧)
完整示例代码:NModbus 官方示例 github.com/NModbus/NModbus/tree/master/src/Samples
协议文档:Modbus TCP 规范 modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf
