一个功能完整、高性能的 Modbus 客户端库,基于.NET 10 平台,支持多种 Modbus 协议变体。
注意:本项目是由 AI 生成的,主要使用了 Trae 以及 Qoder 等工具辅助开发,主要模型是 Qwen-3-Coder、Qwen-3.5-Plus、MiniMax-2.7、GLM-5 等。
dotnet add package Himmelt.ModbusLib- Modbus RTU - 基于 RTU 帧格式的 Modbus 协议,使用 CRC16 校验
- Modbus TCP - 基于 TCP/IP 的标准 Modbus 协议,使用 MBAP 报文头
- Serial (串口) - 通过串口进行 RTU 通信
- TCP - 通过 TCP 网络进行 TCP 或 RTU 帧传输
- UDP - 通过 UDP 网络进行 TCP 或 RTU 帧传输
- Pipe - 通过 .NET Pipe 进行自定义数据流传输
- Channel - 通过 .NET Channel 进行自定义数据流传输
| 传输方式 | RTU 协议 | TCP 协议 |
|---|---|---|
| Serial | ✅ ModbusRtuClient | ❌ |
| TCP | ✅ ModbusTcpClient (ProtocolType.Rtu) | ✅ ModbusTcpClient (ProtocolType.Tcp) |
| UDP | ✅ ModbusUdpClient (ProtocolType.Rtu) | ✅ ModbusUdpClient (ProtocolType.Tcp) |
| Pipe | ✅ ModbusPipeClient (ProtocolType.Rtu) | ✅ ModbusPipeClient (ProtocolType.Tcp) |
| Channel | ✅ ModbusChannelClient (ProtocolType.Rtu) | ✅ ModbusChannelClient (ProtocolType.Tcp) |
- 🚀 异步编程模型,提供卓越的性能
- 🔄 同步方法支持,便于传统应用集成
- 📋 支持所有标准 Modbus 功能码
- ⚙️ 灵活的配置选项
- 🛡️ 完整的错误处理和重试机制
- 💾 内存优化,使用 ArrayPool 减少分配
- 🔀 泛型支持,可直接读写基本数据类型(byte, short, int, long, float, double 等)
- 📊 字节序和字序控制,支持不同平台数据格式
- 🔌 多种传输方式,支持串口、TCP、UDP、Pipe、Channel
- 🎛️ 协议可选,通过网络客户端可灵活选择 RTU 或 TCP 协议
using ModbusLib.Clients;
using ModbusLib.Models;
// 创建 RTU 客户端(串口传输,默认使用 RTU 协议)
var rtuClient = new ModbusRtuClient(new SerialConfig
{
PortName = "COM1",
BaudRate = 9600,
Parity = System.IO.Ports.Parity.None,
DataBits = 8,
StopBits = System.IO.Ports.StopBits.One
});
// 连接并读取数据
await rtuClient.ConnectAsync();
var coils = await rtuClient.ReadCoilsAsync(unitId: 1, startAddress: 0, quantity: 10);using ModbusLib.Clients;
using ModbusLib.Enums;
using ModbusLib.Models;
// TCP 传输 + TCP 协议(标准 Modbus TCP)
var tcpClient = new ModbusTcpClient(new NetworkConfig
{
RemoteHost = "192.168.1.100",
RemotePort = 502
}, protocol: ProtocolType.Tcp); // 或省略 protocol 参数,默认为 Tcp
await tcpClient.ConnectAsync();
await tcpClient.WriteMultipleRegistersAsync(unitId: 1, startAddress: 0, new ushort[] { 100, 200, 300 });// TCP 传输 + RTU 协议(RTU over TCP)
var rtuOverTcpClient = new ModbusTcpClient(new NetworkConfig
{
RemoteHost = "192.168.1.100",
RemotePort = 502
}, protocol: ProtocolType.Rtu);
await rtuOverTcpClient.ConnectAsync();
var registers = await rtuOverTcpClient.ReadHoldingRegistersAsync(unitId: 1, startAddress: 0, quantity: 10);// UDP 传输 + RTU 协议(RTU over UDP)
var rtuOverUdpClient = new ModbusUdpClient(new NetworkConfig
{
RemoteHost = "192.168.1.100",
RemotePort = 502
}, protocol: ProtocolType.Rtu);
await rtuOverUdpClient.ConnectAsync();
var inputs = await rtuOverUdpClient.ReadDiscreteInputsAsync(unitId: 1, startAddress: 0, quantity: 8);// 串口 RTU 客户端(同步)
var rtuClient = new ModbusRtuClient("COM1", 9600);
rtuClient.Connect();
var coils = rtuClient.ReadCoils(unitId: 1, startAddress: 0, quantity: 10);// TCP 客户端 + RTU 协议(同步)
var rtuOverTcpClient = new ModbusTcpClient("192.168.1.100", 502, protocol: ProtocolType.Rtu);
rtuOverTcpClient.Connect();
var registers = rtuOverTcpClient.ReadHoldingRegisters(unitId: 1, startAddress: 0, quantity: 10);// 读取浮点数数组
var floatValues = await client.ReadHoldingRegistersAsync<float>(unitId: 1, startAddress: 0, count: 5);
// 读取双精度浮点数
var doubleValue = await client.ReadHoldingRegistersAsync<double>(unitId: 1, startAddress: 10, count: 1);
// 写入浮点数数组
float[] valuesToWrite = new float[] { 1.23f, 4.56f, 7.89f };
await client.WriteMultipleRegistersAsync(unitId: 1, startAddress: 0, valuesToWrite);
// 写入单个双精度浮点数
await client.WriteMultipleRegistersAsync(unitId: 1, startAddress: 10, 123.456);// 使用小端字节序读取寄存器
var registersLittleEndian = await client.ReadHoldingRegistersAsync(
unitId: 1,
startAddress: 0,
quantity: 10,
byteOrder: ByteOrder.LittleEndian);
// 使用低字在前的字序写入寄存器
await client.WriteMultipleRegistersAsync(
unitId: 1,
startAddress: 0,
values,
byteOrder: ByteOrder.BigEndian,
wordOrder: WordOrder.LowFirst);using ModbusLib.Clients;
using ModbusLib.Enums;
using ModbusLib.Models;
// Pipe 客户端 + TCP 协议(默认)
var pipeSession = new PipeSession();
var pipeTcpClient = new ModbusPipeClient(pipeSession, protocol: ProtocolType.Tcp);
await pipeTcpClient.ConnectAsync();
// Pipe 客户端 + RTU 协议
var pipeRtuClient = new ModbusPipeClient(pipeSession, protocol: ProtocolType.Rtu);
await pipeRtuClient.ConnectAsync();
// Channel 客户端 + TCP 协议(默认)
var channelSession = new ChannelSession();
var channelTcpClient = new ModbusChannelClient(channelSession, protocol: ProtocolType.Tcp);
await channelTcpClient.ConnectAsync();
// Channel 客户端 + RTU 协议
var channelRtuClient = new ModbusChannelClient(channelSession, protocol: ProtocolType.Rtu);
await channelRtuClient.ConnectAsync();提示:Pipe 和 Channel 客户端适用于需要自定义数据源的场景,例如模拟设备、测试环境或通过其他传输层进行通信。
ModbusLib/
├── Clients/ # 客户端实现
│ ├── ModbusClientBase.cs # 客户端基类
│ ├── ModbusRtuClient.cs # RTU 客户端
│ ├── ModbusTcpClient.cs # TCP 客户端
│ ├── ModbusUdpClient.cs # UDP 客户端
│ ├── ModbusPipeClient.cs # Pipe 客户端
│ └── ModbusChannelClient.cs # Channel 客户端
├── Interfaces/ # 核心接口定义
│ ├── IModbusClient.cs # Modbus 客户端接口
│ ├── IModbusProtocol.cs # 协议处理接口
│ └── IModbusTransport.cs # 传输层接口
├── Enums/ # 枚举类型
│ ├── ByteOrder.cs # 字节序枚举
│ ├── WordOrder.cs # 字序枚举
│ ├── ModbusFunction.cs # Modbus 功能码
│ ├── ModbusExceptionCode.cs # Modbus 异常码
│ └── ProtocolType.cs # 协议类型
├── Models/ # 数据模型
│ ├── ModbusRequest.cs # Modbus 请求模型
│ ├── ModbusResponse.cs # Modbus 响应模型
│ ├── SerialConfig.cs # 串口连接配置
│ ├── NetworkConfig.cs # 网络连接配置
│ ├── PipeSession.cs # Pipe 会话模型
│ └── ChannelSession.cs # Channel 会话模型
├── Transports/ # 传输层实现
│ ├── SerialTransport.cs # 串口传输实现
│ ├── TcpTransport.cs # TCP 传输实现
│ ├── UdpTransport.cs # UDP 传输实现
│ ├── PipeTransport.cs # Pipe 传输实现
│ └── ChannelTransport.cs # Channel 传输实现
├── Protocols/ # 协议处理层
│ ├── RtuProtocol.cs # RTU 协议实现
│ └── TcpProtocol.cs # TCP 协议实现
├── Exceptions/ # 异常定义
│ ├── ModbusException.cs # Modbus 异常基类
│ └── ModbusCommunicationExceptions.cs # 通信异常
└── Utils/ # 工具类
├── Crc16Utils.cs # CRC16 校验工具
├── DataConverter.cs # 数据转换工具
└── CancelTokenExtensions.cs # 取消令牌扩展
ModbusLib.Tests/ # 单元测试
├── Clients/ # 客户端测试
├── Functional/ # 功能测试
├── Mocks/ # 模拟对象
├── Transports/ # 传输层测试
└── Utils/ # 工具类测试
# 构建项目
dotnet build
# 运行测试
dotnet test
# 发布 NuGet 包
dotnet packusing ModbusLib.Clients;
using ModbusLib.Models;
// 简化构造(推荐)
var rtuClient = new ModbusRtuClient("COM1", 9600);
// 或使用完整配置
var rtuClient = new ModbusRtuClient(new SerialConfig {
PortName = "COM1",
BaudRate = 9600,
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One
});说明:
ModbusRtuClient固定使用 RTU 协议,无需指定ProtocolType
using ModbusLib.Clients;
using ModbusLib.Enums;
using ModbusLib.Models;
// TCP 传输 + TCP 协议(默认,标准 Modbus TCP)
var tcpClient = new ModbusTcpClient("192.168.1.100", 502);
// 或显式指定
var tcpClient = new ModbusTcpClient("192.168.1.100", 502, protocol: ProtocolType.Tcp);
// TCP 传输 + RTU 协议(RTU over TCP)
var rtuOverTcpClient = new ModbusTcpClient("192.168.1.100", 502, protocol: ProtocolType.Rtu);
// 使用完整配置
var tcpClient = new ModbusTcpClient(new NetworkConfig {
RemoteHost = "192.168.1.100",
RemotePort = 502,
ConnectTimeout = 5000,
ReceiveTimeout = 3000,
SendTimeout = 3000
}, protocol: ProtocolType.Tcp);using ModbusLib.Clients;
using ModbusLib.Enums;
// UDP 传输 + TCP 协议(默认)
var udpClient = new ModbusUdpClient("192.168.1.100", 502);
// UDP 传输 + RTU 协议(RTU over UDP)
var rtuOverUdpClient = new ModbusUdpClient("192.168.1.100", 502, protocol: ProtocolType.Rtu);using ModbusLib.Clients;
using ModbusLib.Enums;
using ModbusLib.Models;
// Pipe + TCP 协议(默认)
var pipeSession = new PipeSession();
var pipeClient = new ModbusPipeClient(pipeSession);
// Pipe + RTU 协议
var pipeRtuClient = new ModbusPipeClient(pipeSession, protocol: ProtocolType.Rtu);using ModbusLib.Clients;
using ModbusLib.Enums;
using ModbusLib.Models;
// Channel + TCP 协议(默认)
var channelSession = new ChannelSession();
var channelClient = new ModbusChannelClient(channelSession);
// Channel + RTU 协议
var channelRtuClient = new ModbusChannelClient(channelSession, protocol: ProtocolType.Rtu);namespace ModbusLib.Enums;
public enum ProtocolType {
Rtu, // RTU 协议(使用 CRC16 校验)
Tcp // TCP 协议(使用 MBAP 报文头)
}| 客户端类型 | 默认协议 | 可选协议 | 典型应用场景 |
|---|---|---|---|
| ModbusRtuClient | RTU | ❌ 不可选 | 串口通信 |
| ModbusTcpClient | TCP | ✅ TCP/RTU | 以太网通信,RTU over TCP |
| ModbusUdpClient | TCP | ✅ TCP/RTU | UDP 广播/组播,RTU over UDP |
| ModbusPipeClient | TCP | ✅ TCP/RTU | 自定义数据流,测试模拟 |
| ModbusChannelClient | TCP | ✅ TCP/RTU | 自定义数据流,测试模拟 |
| 功能码 | 名称 | 描述 |
|---|---|---|
| 0x01 | Read Coils | 读取线圈状态 |
| 0x02 | Read Discrete Inputs | 读取离散输入状态 |
| 0x03 | Read Holding Registers | 读取保持寄存器 |
| 0x04 | Read Input Registers | 读取输入寄存器 |
| 0x05 | Write Single Coil | 写单个线圈 |
| 0x06 | Write Single Register | 写单个寄存器 |
| 0x0F | Write Multiple Coils | 写多个线圈 |
| 0x10 | Write Multiple Registers | 写多个寄存器 |
| 0x17 | Read/Write Multiple Registers | 读写多个寄存器 |
ConnectAsync()/Connect()- 连接到设备DisconnectAsync()/Disconnect()- 断开连接IsConnected- 获取连接状态
ReadCoilsAsync()/ReadCoils()- 读取线圈状态ReadDiscreteInputsAsync()/ReadDiscreteInputs()- 读取离散输入ReadHoldingRegistersAsync()/ReadHoldingRegisters()- 读取保持寄存器ReadInputRegistersAsync()/ReadInputRegisters()- 读取输入寄存器ReadHoldingRegistersRawAsync()/ReadHoldingRegistersRaw()- 读取保持寄存器原始字节ReadInputRegistersRawAsync()/ReadInputRegistersRaw()- 读取输入寄存器原始字节
WriteSingleCoilAsync()/WriteSingleCoil()- 写单个线圈WriteMultipleCoilsAsync()/WriteMultipleCoils()- 写多个线圈WriteSingleRegisterAsync()/WriteSingleRegister()- 写单个寄存器WriteMultipleRegistersAsync()/WriteMultipleRegisters()- 写多个寄存器WriteMultipleRegistersRawAsync()/WriteMultipleRegistersRaw()- 写原始字节到寄存器
ReadWriteMultipleRegistersAsync()/ReadWriteMultipleRegisters()- 读写多个寄存器
ReadHoldingRegistersAsync<T>()/ReadHoldingRegisters<T>()- 泛型读取保持寄存器ReadInputRegistersAsync<T>()/ReadInputRegisters<T>()- 泛型读取输入寄存器WriteMultipleRegistersAsync<T>()/WriteMultipleRegisters<T>()- 泛型写入寄存器
public class SerialConfig {
public string PortName { get; set; } // 串口名称 (如 COM1)
public int BaudRate { get; set; } // 波特率,默认 9600
public Parity Parity { get; set; } // 校验位,默认 None
public int DataBits { get; set; } // 数据位,默认 8
public StopBits StopBits { get; set; } // 停止位,默认 One
public int ReadTimeout { get; set; } // 读取超时(毫秒)
public int WriteTimeout { get; set; } // 写入超时(毫秒)
}public class NetworkConfig {
public string RemoteHost { get; set; } // 远程主机地址
public int RemotePort { get; set; } // 远程端口,默认 502
public int ConnectTimeout { get; set; } // 连接超时(毫秒)
public int ReceiveTimeout { get; set; } // 接收超时(毫秒)
public int SendTimeout { get; set; } // 发送超时(毫秒)
public int ReceiveBufferSize { get; set; } // 接收缓冲区大小
public int SendBufferSize { get; set; } // 发送缓冲区大小
public string? LocalHost { get; set; } // 本地主机地址(可选)
public int? LocalPort { get; set; } // 本地端口(可选)
}库支持所有 unmanaged 类型的泛型读写,包括但不限于:
byte,sbyte- 8 位整数short,ushort- 16 位整数int,uint- 32 位整数long,ulong- 64 位整数float- 单精度浮点数double- 双精度浮点数- 任何
struct类型
// 读取 10 个字节(占用 5 个寄存器)
var bytes = await client.ReadHoldingRegistersAsync<byte>(unitId: 1, startAddress: 0, count: 10);
// 读取 5 个整数(占用 10 个寄存器)
var ints = await client.ReadHoldingRegistersAsync<int>(unitId: 1, startAddress: 10, count: 5);
// 写入浮点数数组
float[] values = new float[] { 1.5f, 2.5f, 3.5f };
await client.WriteMultipleRegistersAsync(unitId: 1, startAddress: 0, values);欢迎提交 Issue 和 Pull Request!
本项目采用 MIT 许可证。