You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# NModbus代码中捕获RX/TX请求响应通信日志?

实现NModbus的请求/响应日志与字节捕获

1. 自定义日志包装流

先实现一个继承自Stream的包装类,用来拦截原始网络流的读写操作,记录带时间戳的通信日志,同时保存请求和响应的字节数组:

public class LoggingStream : Stream
{
    private readonly Stream _innerStream;
    // 保存最近一次发送的请求字节
    public byte[] LastSentBytes { get; private set; }
    // 保存最近一次接收的响应字节
    public byte[] LastReceivedBytes { get; private set; }

    public LoggingStream(Stream innerStream)
    {
        _innerStream = innerStream;
    }

    public override bool CanRead => _innerStream.CanRead;
    public override bool CanSeek => _innerStream.CanSeek;
    public override bool CanWrite => _innerStream.CanWrite;
    public override long Length => _innerStream.Length;
    public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }

    public override void Flush() => _innerStream.Flush();
    public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
    public override void SetLength(long value) => _innerStream.SetLength(value);

    public override int Read(byte[] buffer, int offset, int count)
    {
        int bytesRead = _innerStream.Read(buffer, offset, count);
        if (bytesRead > 0)
        {
            LastReceivedBytes = new byte[bytesRead];
            Array.Copy(buffer, offset, LastReceivedBytes, 0, bytesRead);
            // 打印RX日志(带毫秒级时间戳)
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            string hexData = BitConverter.ToString(LastReceivedBytes).Replace("-", " ");
            Console.WriteLine($"[{timestamp}] RX: {bytesRead} bytes | {hexData}");
        }
        return bytesRead;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        LastSentBytes = new byte[count];
        Array.Copy(buffer, offset, LastSentBytes, 0, count);
        // 打印TX日志(带毫秒级时间戳)
        string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
        string hexData = BitConverter.ToString(LastSentBytes).Replace("-", " ");
        Console.WriteLine($"[{timestamp}] TX: {count} bytes | {hexData}");
        
        _innerStream.Write(buffer, offset, count);
    }
}

2. 修改主代码启用日志与字节捕获

替换原始的TcpClient网络流为自定义日志流,所有Modbus通信都会被自动捕获:

ModbusFactory modbus = new ModbusFactory();
using (TcpClient tcpClient = new TcpClient("127.0.0.1", 5000))
{
    Stream originalStream = tcpClient.GetStream();
    using (LoggingStream loggingStream = new LoggingStream(originalStream))
    {
        var master = modbus.CreateMaster(loggingStream);
        // 执行Modbus读写操作
        var data = master.ReadHoldingRegisters(0, 0, 2);
        
        // 获取并处理请求/响应字节数组
        byte[] requestBytes = loggingStream.LastSentBytes;
        byte[] responseBytes = loggingStream.LastReceivedBytes;
        
        Console.WriteLine("请求字节数组:" + BitConverter.ToString(requestBytes).Replace("-", " "));
        Console.WriteLine("响应字节数组:" + BitConverter.ToString(responseBytes).Replace("-", " "));
    }
}

3. 扩展说明

  • 日志默认输出到控制台,若需要持久化,可将Console.WriteLine替换为写入文件或日志框架(如Serilog、NLog)的逻辑。
  • LastSentBytes和LastReceivedBytes仅保存最近一次通信的字节数据,若需要记录所有历史通信,可在自定义流中添加列表存储。

内容的提问来源于stack exchange,提问作者h1d3r00t

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 04:45:32