以下是基于 C# 的面向对象设计,抽象出公共接口和协议实现

以下是基于 C# 的面向对象设计,抽象出公共接口和协议实现,涵盖 SerialPortProtocol、TcpProtocol、HttpProtocol、WebSocketProtocol、ModbusProtocol 和 MQTTProtocol。每个协议实现为单独的项目,公共接口定义在独立项目中,使用异步编程模式(async/await)确保高效和稳定,代码结构易于扩展。以下内容包含详细的代码示例、注释和项目结构说明。


一、整体设计

1. 设计目标

  • 抽象化:通过接口或抽象类定义通用通信操作(如连接、创建、读、写、关闭),确保协议无关性。
  • 模块化:每个协议实现为独立项目,引用公共接口项目。
  • 异步编程:使用 async/await 提高性能,避免阻塞。
  • 可扩展性:支持新增协议,只需实现公共接口。
  • 稳定性:包含异常处理、资源管理和日志记录。

2. 项目结构

  • Communication.Abstractions:公共接口和抽象类项目。
  • Communication.SerialPort:串口协议实现。
  • Communication.Tcp:TCP 协议实现。
  • Communication.Http:HTTP 协议实现。
  • Communication.WebSocket:WebSocket 协议实现。
  • Communication.Modbus:Modbus 协议实现(支持 RTU 和 TCP)。
  • Communication.MQTT:MQTT 协议实现。
  • Communication.Tests:测试项目,验证各协议实现。

3. 公共接口设计公共接口 ICommunicationProtocol 定义通用通信操作,抽象类 BaseCommunicationProtocol 提供通用功能(如日志记录)。


二、公共接口项目(Communication.Abstractions)

1. 项目结构

Communication.Abstractions/
├── ICommunicationProtocol.cs
├── BaseCommunicationProtocol.cs

2. 代码实现ICommunicationProtocol.cs csharp

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.Abstractions
{
    /// 
    /// 定义通信协议的通用接口,包含连接、读写、关闭等操作
    /// 
    public interface ICommunicationProtocol : IDisposable
    {
        /// 
        /// 异步连接到目标设备
        /// 
        /// 取消令牌
        /// Task
        Task ConnectAsync(CancellationToken cancellationToken);

        /// 
        /// 异步读取数据
        /// 
        /// 存储读取数据的缓冲区
        /// 取消令牌
        /// 读取的字节数
        Task ReadAsync(byte[] buffer, CancellationToken cancellationToken);

        /// 
        /// 异步写入数据
        /// 
        /// 要写入的数据
        /// 取消令牌
        /// Task
        Task WriteAsync(byte[] data, CancellationToken cancellationToken);

        /// 
        /// 异步关闭连接
        /// 
        /// 取消令牌
        /// Task
        Task CloseAsync(CancellationToken cancellationToken);

        /// 
        /// 获取连接状态
        /// 
        bool IsConnected { get; }
    }
}

BaseCommunicationProtocol.cscsharp

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace Communication.Abstractions
{
    /// 
    /// 通信协议的抽象基类,提供通用功能(如日志记录)
    /// 
    public abstract class BaseCommunicationProtocol : ICommunicationProtocol
    {
        protected readonly ILogger _logger;

        protected BaseCommunicationProtocol(ILogger logger)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public abstract bool IsConnected { get; }

        public abstract Task ConnectAsync(CancellationToken cancellationToken);

        public abstract Task ReadAsync(byte[] buffer, CancellationToken cancellationToken);

        public abstract Task WriteAsync(byte[] data, CancellationToken cancellationToken);

        public abstract Task CloseAsync(CancellationToken cancellationToken);

        public virtual void Dispose()
        {
            // 实现 IDisposable,子类需重写以释放资源
        }

        /// 
        /// 记录日志的辅助方法
        /// 
        protected void LogInformation(string message)
        {
            _logger.LogInformation($"[{GetType().Name}] {message}");
        }

        protected void LogError(string message, Exception ex)
        {
            _logger.LogError(ex, $"[{GetType().Name}] {message}");
        }
    }
}
  • 说明:
    • ICommunicationProtocol 定义异步操作接口,确保一致性。
    • BaseCommunicationProtocol 提供日志记录和基础结构,子类继承后实现具体协议。
    • 使用 ILogger(Microsoft.Extensions.Logging)记录日志,便于调试和监控。

三、协议实现项目以下为每个协议的实现,均引用 Communication.Abstractions 项目,使用异步方式,包含详细注释。1. SerialPortProtocol(Communication.SerialPort)项目依赖

  • System.IO.Ports
  • Communication.Abstractions

代码实现(SerialPortProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.SerialPort
{
    public class SerialPortProtocol : BaseCommunicationProtocol
    {
        private readonly SerialPort _serialPort;
        private readonly string _portName;
        private readonly int _baudRate;

        public SerialPortProtocol(string portName, int baudRate, ILogger logger)
            : base(logger)
        {
            _portName = portName ?? throw new ArgumentNullException(nameof(portName));
            _baudRate = baudRate;
            _serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
        }

        public override bool IsConnected => _serialPort?.IsOpen ?? false;

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                    LogInformation($"Connected to serial port {_portName} at {_baudRate} baud.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to connect to serial port.", ex);
                throw;
            }
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("Serial port is not connected.");

                int bytesRead = await Task.Run(() => _serialPort.Read(buffer, 0, buffer.Length), cancellationToken);
                LogInformation($"Read {bytesRead} bytes from serial port.");
                return bytesRead;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from serial port.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("Serial port is not connected.");

                await Task.Run(() => _serialPort.Write(data, 0, data.Length), cancellationToken);
                LogInformation($"Wrote {data.Length} bytes to serial port.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to serial port.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                    LogInformation("Serial port closed.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to close serial port.", ex);
                throw;
            }
        }

        public override void Dispose()
        {
            _serialPort?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 System.IO.Ports.SerialPort 实现串口通信。
    • 构造函数接收端口号和波特率,初始化串口。
    • 异步方法通过 Task.Run 包装同步操作,支持取消令牌。
    • 日志记录连接、读写和关闭操作。

2. TcpProtocol(Communication.Tcp)项目依赖

  • System.Net.Sockets
  • Communication.Abstractions

代码实现(TcpProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.Tcp
{
    public class TcpProtocol : BaseCommunicationProtocol
    {
        private readonly TcpClient _tcpClient;
        private readonly string _host;
        private readonly int _port;
        private NetworkStream _stream;

        public TcpProtocol(string host, int port, ILogger logger)
            : base(logger)
        {
            _host = host ?? throw new ArgumentNullException(nameof(host));
            _port = port;
            _tcpClient = new TcpClient();
        }

        public override bool IsConnected => _tcpClient?.Connected ?? false;

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (!_tcpClient.Connected)
                {
                    await _tcpClient.ConnectAsync(_host, _port, cancellationToken);
                    _stream = _tcpClient.GetStream();
                    LogInformation($"Connected to {_host}:{_port}.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to connect to TCP server.", ex);
                throw;
            }
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("TCP client is not connected.");

                int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken);
                LogInformation($"Read {bytesRead} bytes from TCP server.");
                return bytesRead;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from TCP server.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("TCP client is not connected.");

                await _stream.WriteAsync(data, 0, data.Length, cancellationToken);
                LogInformation($"Wrote {data.Length} bytes to TCP server.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to TCP server.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_tcpClient.Connected)
                {
                    _stream?.Close();
                    _tcpClient.Close();
                    LogInformation("TCP connection closed.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to close TCP connection.", ex);
                throw;
            }
        }

        public override void Dispose()
        {
            _stream?.Dispose();
            _tcpClient?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 TcpClient 实现 TCP 通信。
    • 异步方法直接调用 ConnectAsync、ReadAsync 和 WriteAsync。
    • 确保资源通过 Dispose 释放。

3. HttpProtocol(Communication.Http)项目依赖

  • System.Net.Http
  • Communication.Abstractions

代码实现(HttpProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.Http
{
    public class HttpProtocol : BaseCommunicationProtocol
    {
        private readonly HttpClient _httpClient;
        private readonly string _baseUrl;

        public HttpProtocol(string baseUrl, ILogger logger)
            : base(logger)
        {
            _baseUrl = baseUrl ?? throw new ArgumentNullException(nameof(baseUrl));
            _httpClient = new HttpClient();
        }

        public override bool IsConnected => true; // HTTP 是无状态协议,假设始终“连接”

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            LogInformation($"HTTP protocol initialized for {_baseUrl}.");
            // HTTP 无需显式连接
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                HttpResponseMessage response = await _httpClient.GetAsync(_baseUrl, cancellationToken);
                response.EnsureSuccessStatusCode();
                byte[] data = await response.Content.ReadAsByteArrayAsync(cancellationToken);
                Array.Copy(data, buffer, Math.Min(data.Length, buffer.Length));
                LogInformation($"Read {data.Length} bytes from {_baseUrl}.");
                return data.Length;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from HTTP server.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                var content = new ByteArrayContent(data);
                HttpResponseMessage response = await _httpClient.PostAsync(_baseUrl, content, cancellationToken);
                response.EnsureSuccessStatusCode();
                LogInformation($"Wrote {data.Length} bytes to {_baseUrl}.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to HTTP server.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            LogInformation("HTTP protocol does not require explicit closing.");
            // HTTP 无需显式关闭
        }

        public override void Dispose()
        {
            _httpClient?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 HttpClient 实现 HTTP 通信。
    • HTTP 是无状态协议,ConnectAsync 和 CloseAsync 不执行实际操作。
    • 支持 GET(读)和 POST(写)请求。

4. WebSocketProtocol(Communication.WebSocket)项目依赖

  • System.Net.WebSockets
  • Communication.Abstractions

代码实现(WebSocketProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.WebSocket
{
    public class WebSocketProtocol : BaseCommunicationProtocol
    {
        private readonly ClientWebSocket _webSocket;
        private readonly Uri _uri;

        public WebSocketProtocol(string uri, ILogger logger)
            : base(logger)
        {
            _uri = new Uri(uri ?? throw new ArgumentNullException(nameof(uri)));
            _webSocket = new ClientWebSocket();
        }

        public override bool IsConnected => _webSocket?.State == WebSocketState.Open;

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_webSocket.State != WebSocketState.Open)
                {
                    await _webSocket.ConnectAsync(_uri, cancellationlaboratory_diagnostic_techniques
                    LogInformation($"Connected to WebSocket {_uri}.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to connect to WebSocket.", ex);
                throw;
            }
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("WebSocket is not connected.");

                var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), cancellationToken);
                LogInformation($"Read {result.Count} bytes from WebSocket.");
                return result.Count;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from WebSocket.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("WebSocket is not connected.");

                await _webSocket.SendAsync(new ArraySegment(data), WebSocketMessageType.Binary, true, cancellationToken);
                LogInformation($"Wrote {data.Length} bytes to WebSocket.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to WebSocket.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (IsConnected)
                {
                    await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken);
                    LogInformation("WebSocket connection closed.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to close WebSocket.", ex);
                throw;
            }
        }

        public override void Dispose()
        {
            _webSocket?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 ClientWebSocket 实现 WebSocket 通信。
    • 支持二进制数据的发送和接收。
    • 异步方法支持取消操作。

5. ModbusProtocol(Communication.Modbus)项目依赖

  • NModbus(通过 NuGet 安装)
  • Communication.Abstractions

代码实现(ModbusProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using Modbus.Device;
using System;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.Modbus
{
    public class ModbusProtocol : BaseCommunicationProtocol
    {
        private readonly SerialPort _serialPort;
        private ModbusSerialMaster _master;
        private readonly byte _slaveId;

        public ModbusProtocol(string portName, int baudRate, byte slaveId, ILogger logger)
            : base(logger)
        {
            _serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
            _slaveId = slaveId;
        }

        public override bool IsConnected => _serialPort?.IsOpen ?? false;

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                    _master = ModbusSerialMaster.CreateRtu(_serialPort);
                    LogInformation($"Connected to Modbus RTU on {_serialPort.PortName}.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to connect to Modbus RTU.", ex);
                throw;
            }
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("Modbus is not connected.");

                // 读取保持寄存器(功能码 03)
                ushort[] registers = await Task.Run(() => _master.ReadHoldingRegisters(_slaveId, 0, (ushort)(buffer.Length / 2)), cancellationToken);
                Buffer.BlockCopy(registers, 0, buffer, 0, buffer.Length);
                LogInformation($"Read {buffer.Length} bytes from Modbus RTU.");
                return buffer.Length;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from Modbus RTU.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("Modbus is not connected.");

                ushort[] registers = new ushort[data.Length / 2];
                Buffer.BlockCopy(data, 0, registers, 0, data.Length);
                await Task.Run(() => _master.WriteMultipleRegisters(_slaveId, 0, registers), cancellationToken);
                LogInformation($"Wrote {data.Length} bytes to Modbus RTU.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to Modbus RTU.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                    LogInformation("Modbus RTU connection closed.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to close Modbus RTU.", ex);
                throw;
            }
        }

        public override void Dispose()
        {
            _serialPort?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 NModbus 实现 Modbus RTU 协议。
    • 支持保持寄存器的读写操作。
    • 数据以字节数组形式传递,适配接口定义。

6. MQTTProtocol(Communication.MQTT)项目依赖

  • MQTTnet(通过 NuGet 安装)
  • Communication.Abstractions

代码实现(MqttProtocol.cs)csharp

using Communication.Abstractions;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Client;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.MQTT
{
    public class MqttProtocol : BaseCommunicationProtocol
    {
        private readonly IMqttClient _mqttClient;
        private readonly string _brokerAddress;
        private readonly string _topic;

        public MqttProtocol(string brokerAddress, string topic, ILogger logger)
            : base(logger)
        {
            _brokerAddress = brokerAddress ?? throw new ArgumentNullException(nameof(brokerAddress));
            _topic = topic ?? throw new ArgumentNullException(nameof(topic));
            var factory = new MqttFactory();
            _mqttClient = factory.CreateMqttClient();
        }

        public override bool IsConnected => _mqttClient?.IsConnected ?? false;

        public override async Task ConnectAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (!_mqttClient.IsConnected)
                {
                    var options = new MqttClientOptionsBuilder()
                        .WithTcpServer(_brokerAddress)
                        .Build();
                    await _mqttClient.ConnectAsync(options, cancellationToken);
                    LogInformation($"Connected to MQTT broker {_brokerAddress}.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to connect to MQTT broker.", ex);
                throw;
            }
        }

        public override async Task ReadAsync(byte[] buffer, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("MQTT client is not connected.");

                var tcs = new TaskCompletionSource();
                _mqttClient.ApplicationMessageReceivedAsync += e =>
                {
                    byte[] payload = e.ApplicationMessage.Payload;
                    Array.Copy(payload, buffer, Math.Min(payload.Length, buffer.Length));
                    tcs.SetResult(payload.Length);
                    return Task.CompletedTask;
                };

                await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(_topic).Build());
                LogInformation($"Subscribed to MQTT topic {_topic}.");
                return await tcs.Task;
            }
            catch (Exception ex)
            {
                LogError("Failed to read from MQTT.", ex);
                throw;
            }
        }

        public override async Task WriteAsync(byte[] data, CancellationToken cancellationToken)
        {
            try
            {
                if (!IsConnected)
                    throw new InvalidOperationException("MQTT client is not connected.");

                var message = new MqttApplicationMessageBuilder()
                    .WithTopic(_topic)
                    .WithPayload(data)
                    .Build();
                await _mqttClient.PublishAsync(message, cancellationToken);
                LogInformation($"Published {data.Length} bytes to MQTT topic {_topic}.");
            }
            catch (Exception ex)
            {
                LogError("Failed to write to MQTT.", ex);
                throw;
            }
        }

        public override async Task CloseAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_mqttClient.IsConnected)
                {
                    await _mqttClient.DisconnectAsync(cancellationToken);
                    LogInformation("MQTT connection closed.");
                }
            }
            catch (Exception ex)
            {
                LogError("Failed to close MQTT connection.", ex);
                throw;
            }
        }

        public override void Dispose()
        {
            _mqttClient?.Dispose();
            base.Dispose();
        }
    }
}
  • 说明:
    • 使用 MQTTnet 实现 MQTT 通信。
    • 支持订阅和发布消息到指定主题。
    • 异步方法适配接口定义。

四、测试项目(Communication.Tests)测试代码示例以下是一个测试程序,验证所有协议的实现。csharp

using Communication.Abstractions;
using Communication.SerialPort;
using Communication.Tcp;
using Communication.Http;
using Communication.WebSocket;
using Communication.Modbus;
using Communication.MQTT;
using Microsoft.Extensions.Logging;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
        
        // 测试串口协议
        var serialPort = new SerialPortProtocol("COM3", 9600, loggerFactory.CreateLogger());
        await TestProtocolAsync(serialPort, "SerialPort");

        // 测试 TCP 协议
        var tcp = new TcpProtocol("127.0.0.1", 12345, loggerFactory.CreateLogger());
        await TestProtocolAsync(tcp, "TCP");

        // 测试 HTTP 协议
        var http = new HttpProtocol("http://example.com", loggerFactory.CreateLogger());
        await TestProtocolAsync(http, "HTTP");

        // 测试 WebSocket 协议
        var webSocket = new WebSocketProtocol("ws://echo.websocket.org", loggerFactory.CreateLogger());
        await TestProtocolAsync(webSocket, "WebSocket");

        // 测试 Modbus 协议
        var modbus = new ModbusProtocol("COM3", 9600, 1, loggerFactory.CreateLogger());
        await TestProtocolAsync(modbus, "Modbus");

        // 测试 MQTT 协议
        var mqtt = new MqttProtocol("broker.hivemq.com", "test/topic", loggerFactory.CreateLogger());
        await TestProtocolAsync(mqtt, "MQTT");
    }

    static async Task TestProtocolAsync(ICommunicationProtocol protocol, string protocolName)
    {
        try
        {
            await protocol.ConnectAsync(CancellationToken.None);
            Console.WriteLine($"{protocolName} connected: {protocol.IsConnected}");

            byte[] data = Encoding.UTF8.GetBytes("Test Data");
            await protocol.WriteAsync(data, CancellationToken.None);

            byte[] buffer = new byte[1024];
            int bytesRead = await protocol.ReadAsync(buffer, CancellationToken.None);
            Console.WriteLine($"{protocolName} read: {Encoding.UTF8.GetString(buffer, 0, bytesRead)}");

            await protocol.CloseAsync(CancellationToken.None);
            Console.WriteLine($"{protocolName} closed.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"{protocolName} error: {ex.Message}");
        }
        finally
        {
            protocol.Dispose();
        }
    }
}
  • 说明:
    • 测试程序统一测试各协议的连接、读写和关闭功能。
    • 使用 ILogger 记录日志,便于调试。
    • 需根据实际环境调整参数(如 COM 端口、IP 地址、URL)。

五、注意事项与优化1. 注意事项

  • 环境配置:
    • 串口协议:确保 COM 端口可用,使用 USB-to-RS232/RS485 转换器。
    • TCP/WebSocket:确保目标服务器运行并监听指定端口。
    • HTTP:确保目标 URL 可访问。
    • Modbus:使用 Modbus Slave 模拟器或实际设备,配置正确参数。
    • MQTT:使用公共 MQTT 经纪人(如 broker.hivemq.com)或本地经纪人。
  • 依赖管理:
    • 安装 NModbus 和 MQTTnet 库。
    • 使用 Microsoft.Extensions.Logging 进行日志记录。
  • 异常处理:
    • 各协议实现包含完善的异常处理。
    • 测试时确保目标设备或模拟器正常运行。

2. 优化建议

  • 依赖注入:使用 Microsoft.Extensions.DependencyInjection 管理协议实例。
  • 配置管理:通过 IConfiguration 读取协议参数(如端口、URL)。
  • 重试机制:为连接和读写操作添加重试逻辑。
  • 单元测试:使用 xUnit 或 NUnit 编写单元测试,确保协议实现稳定。
  • 性能优化:
    • 使用对象池管理 TcpClient 和 HttpClient。
    • 优化 Modbus 和 MQTT 的批量操作。

六、扩展性

  • 新增协议:
    1. 创建新项目(如 Communication.NewProtocol)。
    2. 引用 Communication.Abstractions。
    3. 实现 ICommunicationProtocol 接口。
    4. 在测试项目中添加新协议的测试代码。
  • 示例扩展协议:
    • CAN 协议:使用第三方 CAN 库(如 Peak CAN)。
    • Profibus:使用专用硬件和驱动程序。

七、总结

  • 公共接口:ICommunicationProtocol 和 BaseCommunicationProtocol 提供统一的抽象接口和基础功能。
  • 协议实现:六个协议(SerialPort、TCP、HTTP、WebSocket、Modbus、MQTT)均以异步方式实现,支持日志和异常处理。
  • 测试项目:统一测试程序验证各协议功能。
  • 可扩展性:模块化设计便于添加新协议。
  • 稳定性:异步编程、日志记录和资源管理确保高效稳定。

如果需要更详细的某协议实现(如 Modbus TCP 的扩展)、特定场景优化、模拟器配置截图(需通过其他方式提供),或进一步的测试用例,请告诉我!

你可能感兴趣的:(通讯协议,c#,开发语言)