一、整体层级架构(核心认知)
从底层到上层依次递进,所有高层类均基于原生Socket封装:
原生底层:Socket(TCP/UDP通用,自由度最高)
高层封装:
TCP体系:TcpListener(服务端监听)、TcpClient(客户端通信)
UDP体系:UdpClient(无连接报文通信)
Modbus协议层:NModbus4(基于TcpClient/串口封装,专属工业协议)
核心区别:
TCP:面向连接、可靠有序、存在粘包问题
UDP:无连接、不可靠、无粘包、单报文单次收发
NModbus4:仅支持TCP/串口RTU/ASCII,不支持UDP
通用命名空间
// 基础网络 using System.Net; using System.Net.Sockets; // NModbus4 工业协议 using Modbus.Device; using Modbus.Data;二、原生 Socket 全套API(同步+异步)
1. 构造方法
// TCP 套接字 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // UDP 套接字 new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);2. TCP 核心方法
同步方法
Bind():绑定本机IP和端口(服务端必备)
Listen(int backlog):开启TCP监听
Accept():阻塞等待客户端连接,返回新通信Socket
Connect():客户端连接服务端
Send()/Receive():收发字节数据
异步 Task 方法(推荐)
Task<Socket> AcceptAsync(SocketAsyncEventArgs e); Task ConnectAsync(EndPoint remoteEP); Task ConnectAsync(string host, int port); Task<int> SendAsync(ArraySegment<byte> buffer, SocketFlags socketFlags); Task<int> ReceiveAsync(ArraySegment<byte> buffer, SocketFlags socketFlags);3. UDP 核心方法
UDP无连接,无需握手,支持指定远端收发
同步方法
Bind():绑定本地端口(接收数据必备)
SendTo(byte[], IPEndPoint):指定地址发送报文
ReceiveFrom(byte[], ref IPEndPoint):接收并获取发送方地址
Connect():锁定远端地址,简化后续收发
异步 Task 方法
Task<int> SendToAsync(ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEP); Task<int> ReceiveFromAsync(ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEP);4. Socket 通用方法
Shutdown(SocketShutdown.Both):优雅关闭收发通道
Close()/Dispose():释放套接字资源
SetSocketOption():设置超时、缓冲区、端口复用等
三、TCP 高层封装:TcpListener(服务端)
1. 核心功能
封装Socket的Bind+Listen,专门用于TCP服务端监听,不直接收发数据
2. 全套API
同步:Start()、Stop()
异步
Task<TcpClient> AcceptTcpClientAsync(); Task<Socket> AcceptSocketAsync();使用流程:Start() → 异步Accept获取客户端通道 → 基于TcpClient通信
四、TCP 高层封装:TcpClient(客户端/会话通道)
1. 核心功能
封装TCP连接和数据流,是NModbus4 TCP主站的核心依赖
2. 全套API
同步:Connect()、Close()、GetStream()
异步连接方法
Task ConnectAsync(string host, int port); Task ConnectAsync(IPAddress address, int port); Task ConnectAsync(IPAddress[] addresses, int port);数据流异步读写(NetworkStream)
NetworkStream stream = tcpClient.GetStream(); Task<int> ReadAsync(byte[] buffer, int offset, int count); Task WriteAsync(byte[] buffer, int offset, int count);常用属性:Connected(连接状态)、Client(获取底层原生Socket)
五、UDP 高层封装:UdpClient
1. 核心功能
简化UDP报文收发,无连接模式,单报文独立传输,无粘包
2. 全套API
同步:Send()、Receive()、Connect()、Close()
异步核心方法
Task<UdpReceiveResult> ReceiveAsync(); Task<int> SendAsync(byte[] datagram, int bytes); Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint endPoint);备注:UdpReceiveResult 包含 Buffer(数据)、RemoteEndPoint(发送方地址)
六、NModbus4 全套异步API(工业Modbus TCP/RTU)
1. 核心角色说明
ModbusIpMaster:Modbus TCP 主站(客户端,主动读写设备)
ModbusSerialMaster:Modbus RTU/ASCII 串口主站
ModbusTcpSlave:Modbus TCP 从站(服务端,模拟设备)
关键限制:NModbus4不支持UDP,无任何UDP相关封装
2. ModbusIpMaster 全套异步读写API(最常用)
// 01 读线圈 Task<bool[]> ReadCoilsAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints); // 02 读离散输入 Task<bool[]> ReadInputsAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints); // 03 读保持寄存器 Task<ushort[]> ReadHoldingRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints); // 04 读输入寄存器 Task<ushort[]> ReadInputRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints); // 05 写单个线圈 Task WriteSingleCoilAsync(byte slaveAddress, ushort address, bool value); // 06 写单个保持寄存器 Task WriteSingleRegisterAsync(byte slaveAddress, ushort address, ushort value); // 15 写多个线圈 Task WriteMultipleCoilsAsync(byte slaveAddress, ushort startAddress, bool[] values); // 16 写多个保持寄存器 Task WriteMultipleRegistersAsync(byte slaveAddress, ushort startAddress, ushort[] values); // 拓展小众接口 Task<byte> ReadExceptionStatusAsync(byte slaveAddress); Task<ModbusCommEvent> ReadCommEventCounterAsync(byte slaveAddress); Task<ModbusSlaveIdentity> ReportSlaveIdentityAsync(byte slaveAddress);3. Modbus 主站创建方式
// 方式1:内部自动创建TcpClient(最简) ModbusIpMaster master = ModbusIpMaster.CreateIp("127.0.0.1", 502); // 方式2:复用自定义TcpClient(推荐,可控连接生命周期) TcpClient tcp = new TcpClient(); await tcp.ConnectAsync("127.0.0.1", 502); ModbusIpMaster master = ModbusIpMaster.CreateIp(tcp); // 超时配置 master.Transport.ReadTimeout = 1500; master.Transport.WriteTimeout = 1500;4. Modbus 从站(Slave)API
从站无异步读写接口,直接操作内存寄存器,同步运行
// 创建从站并启动监听 ModbusTcpSlave slave = ModbusTcpSlave.CreateTcp(1, IPAddress.Any, 502); slave.DataStore = ModbusDataStoreFactory.CreateDefault(); slave.Listen(); // 直接操作寄存器 slave.DataStore.HoldingRegisters[0] = 100; slave.DataStore.CoilDiscretes[0] = true; // 停止服务 slave.Stop(); slave.Dispose();5. Modbus RTU 串口主站
方法签名与TCP主站完全一致,仅创建方式不同
ModbusSerialMaster rtuMaster = ModbusSerialMaster.CreateRtu(serialPort); // 同样调用 ReadXXXAsync / WriteXXXAsync 系列方法七、核心使用注意事项(高频避坑)
粘包问题:TCP、TcpClient、Modbus TCP均存在粘包,需手动分包;UDP无粘包
UDP限制:NModbus4不支持Modbus UDP,如需使用需手动基于UdpClient拼装解析报文
版本区分:ModbusIpMaster(TCP无CRC)、ModbusSerialMaster(RTU带CRC),不可混用
连接管理:NModbus4依赖TcpClient连接,连接断开后需重新创建主站,无法自动重连
异常处理:所有Async方法超时、断线、设备异常均会抛异常,必须try-catch
资源释放:TcpClient、UdpClient、Modbus主从站均需Dispose释放套接字资源
SlaveId规则:Modbus TCP常规设备SlaveId填1,串口RTU需严格匹配设备地址
八、最终层级速查表
类名 | 通信模式 | 核心异步方法 | 适配NModbus4 |
|---|---|---|---|
Socket(TCP) | 底层TCP | AcceptAsync、ConnectAsync、SendAsync、ReceiveAsync | 需包装为TcpClient |
Socket(UDP) | 底层UDP | SendToAsync、ReceiveFromAsync | 不支持 |
TcpListener | TCP服务端监听 | AcceptTcpClientAsync | 支持(自定义从站) |
TcpClient | TCP客户端 | ConnectAsync、ReadAsync、WriteAsync | ✅ 核心依赖 |
UdpClient | UDP报文通信 | ReceiveAsync、SendAsync | 不支持 |
ModbusIpMaster | Modbus TCP主站 | 全系列Read/WriteAsync | —— |
ModbusTcpSlave | Modbus TCP从站 | 无异步接口 | —— |