如何在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
相关产品推荐
相关产品推荐

