C# 实现 Modbus TCP 通信

C# 实现 Modbus TCP 通信 结合主流开源库与底层协议实现

一、核心实现方案

1. 使用 NModbus 库(推荐)

安装依赖

bash 复制代码
Install-Package NModbus  # NuGet 安装

客户端代码示例

c# 复制代码
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 起始地址+数量

代码实现

c# 复制代码
// 构建读寄存器请求帧 (功能码 0x03)
byte[] BuildReadRequest(ushort startAddr, ushort count)
{
    byte[] frame = new byte[12];
    // MBAP 头
    frame[0] = 0x00; frame[1] = 0x01;  // 事务ID
    frame[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. 服务端实现(模拟设备)
c# 复制代码
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. 错误处理与重连
c# 复制代码
try
{
    master.WriteSingleRegister(0, 100); // 写入寄存器
}
catch (SocketException ex)
{
    Console.WriteLine($"网络错误: {ex.Message}");
    Reconnect(client); // 重连逻辑
}
catch (ModbusException ex)
{
    Console.WriteLine($"Modbus错误码: {ex.ErrorCode}");
}
3. 批量操作优化
c# 复制代码
// 一次读取多个寄存器(减少请求次数)
ushort[] batchData = master.ReadHoldingRegisters(0, 50);

// 批量写入寄存器
master.WriteMultipleRegisters(0, new ushort[]{10, 20, 30});

四、扩展应用

  1. 多设备管理

    使用 Dictionary<string, TcpClient>管理多个设备连接。

  2. 安全通信

    通过 VPN 或 TLS 加密隧道(需设备支持)。

  3. 与工业系统集成

    • 读取 PLC 数据(如西门子 S7-1200)
    • 连接 SCADA 系统(如 Ignition、WinCC)。

🔗 五、资源推荐

  1. 源码推荐
  2. 调试工具
    • Modbus Poll(测试客户端)
    • Wireshark(抓包分析协议帧)

完整示例代码:NModbus 官方示例 github.com/NModbus/NModbus/tree/master/src/Samples

协议文档:Modbus TCP 规范 modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf

相关推荐
油丶酸萝卜别吃5 小时前
utils.js 说明文档
开发语言·javascript·ecmascript
leisoo80978 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
不会代码的小猴8 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
青瓦梦滋9 小时前
传输层UDP/TCP协议
linux·网络·c++·网络协议·tcp/ip·udp
一只旭宝9 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
椒颜皮皮虾྅11 小时前
OpenVINO C# API 3.3.1:支持OpenVINO 2026.3及GenAI增强
人工智能·c#·openvino
coder!mq11 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding11 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ12 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大12 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言