基于C# 和 NModbus 库的 Modbus TCP 通信示例源码

基于 C# 和 NModbus 库 的 Modbus TCP 通信示例源码 ,包含 客户端(Master) 和 服务器端(Slave) 的实现,支持读写寄存器、线圈等操作。


一、环境准备

  1. NuGet 依赖安装

    在项目中安装 NModbus库(支持 .NET Framework 和 .NET Core):

    csharp 复制代码
    Install-Package NModbus
  2. 网络配置 Modbus TCP 默认端口为 502 ,需确保防火墙开放该端口。 从站地址(Unit ID)范围:1~247(默认 1)。


二、Modbus TCP 客户端(Master)示例

1. 同步读写操作
csharp 复制代码
using System;
using System.Net.Sockets;
using Modbus.Device;

class ModbusTcpClientDemo
{
    static void Main()
    {
        string ipAddress = "192.168.1.100"; // 从站 IP
        int 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. 异步读写操作
csharp 复制代码
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. 基础服务器实现
csharp 复制代码
using System;
using System.Net;
using System.Net.Sockets;
using Modbus.Device;
using Modbus.Utility;

class ModbusTcpSlaveDemo
{
    static void Main()
    {
        ushort slaveId = 1;        // 从站 ID
        int 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. 自定义数据处理(事件驱动)
csharp 复制代码
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/contentcso/93804.html

四、关键功能说明

  1. 数据存储区 保持寄存器(Holding Registers) :地址从 0 开始 ,用于存储可读写的 16 位数据(如传感器值)。 输入寄存器(Input Registers) :地址从 0 开始 ,仅支持读取(如设备状态)。 线圈(Coils) :布尔值(0/1),地址从 0 开始 。 离散输入(Discrete Inputs):只读布尔值。
  2. 异常处理 捕获 ModbusSlaveException处理协议错误(如非法地址)。 设置超时时间:master.Transport.ReadTimeout = 3000;(单位:毫秒)。
  3. 性能优化 批量读写:使用 ReadMultipleRegisters和 WriteMultipleRegisters减少网络开销。 多线程处理:服务器端使用异步监听(async/await)提升并发能力。

五、测试工具推荐

  1. Modbus Poll (Windows) 功能:模拟主站,发送读写请求,验证从站响应。 下载地址:Modbus Poll www.modbusdriver.com/software/modbus-poll.html
  2. Modbus Slave(Windows) 功能:模拟从站,提供数据存储和响应。
相关推荐
qq_406981032 分钟前
什么是顶层 const什么是底层const
开发语言·c++
Eider199821 分钟前
python基础语法之并发基础练习
开发语言·python
#麻辣小龙虾#26 分钟前
网页布局css中flex+margin的组合布局技巧
开发语言·前端·javascript
云和数据.ChenGuang29 分钟前
python和java的try
java·开发语言·python
我是唐青枫29 分钟前
Kotlin Inheritance(继承)详解:语法、原理、实战 Demo
开发语言·kotlin
叼烟扛炮29 分钟前
Linux 学习笔记(四十五):Web 安全基石——Cookie、Session 与 HTTPS 原理解析
linux·前端·网络·笔记·学习·tcp/ip·安全
ly768940 分钟前
从 OpenAPI 到多语言 SDK 生成:Java 服务端契约漂移与生成器版本治理
java·开发语言·openapi·java 21·版本兼容·契约漂移·sdk 生成
lqbzlll1 小时前
CVE-2026-91403 排查指南:Java JSSE 信任链漏洞的根因、影响范围和修复步骤
java·开发语言·信任链
CarIise1 小时前
AOP 概念的引入
java·开发语言
凉茶钱1 小时前
多态:从虚函数语法到虚表寻址,一次讲透动态绑定
开发语言·c++·多态