C# 通讯设备基类(串口和网络通讯)

本文介绍了两个通信接口:IDeviceConnect用于连接设备,支持数据监控和状态管理。SocketConnectionDevice和SerialPortConnectionDevice分别基于Socket和串口进行设备连接,提供发送/接收数据的方法和异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonLib.Communication
{
    /// <summary>
    /// 可连接设备接口
    /// </summary>
    public interface IDeviceConnect : IDisposable
    {
        /// <summary>
        /// 数据监控委托。参数1为数据传输方向"Send"/"Receive",参数2为数据字节数组。
        /// </summary>
        Action<string, byte[]> DataMonitor { get; set; }

        /// <summary>
        /// 连接状态,"Connected"-已连接、"UnConnected"-未连接 等等其它状态。
        /// </summary>
        string ConnectState { get; set; }

        /// <summary>
        /// 设置通参数
        /// </summary>
        /// <param name="parameters">通讯参数接口对象(具体参数详见实现类)</param>
        void SetCommunicationParameters(IParameters parameters);

        /// <summary>
        /// 连接设备
        /// </summary>
        /// <returns></returns>
        bool Connect();

        /// <summary>
        /// 断开设备
        /// </summary>
        void Disconnect();

        /// <summary>
        /// 发送并读取数据(读取指定长度),可单发,也可单读。
        /// </summary>
        /// <param name="sendBytes">发送字节集合,如果为null或者长度为零表示不发送只读取。</param>
        /// <param name="readDelay">回读数据前延时时间,如果小于等于零表示不延时。</param>
        /// <param name="readLength">读取长度,如果小于等于令表示不读取。</param>
        /// <param name="readTimeout">读取超时时间,单位毫秒。</param>
        /// <returns></returns>
        List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout);

        /// <summary>
        /// 发送并读取数据(读取串口缓冲区所有数据),必需有读回送。
        /// </summary>
        /// <param name="sendBytes">发送字节集合,如果为null或者长度为零表示不发送只读取。</param>
        /// <param name="readDelay">回读数据前延时时间,如果小于等于零表示不延时。</param>
        /// <param name="readTimeout">读取超时时间,单位毫秒。</param>
        /// <returns></returns>
        List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout);

        /// <summary>
        /// 终止读写数据
        /// </summary>
        void AbortSRBytes();

    }
}

SocketCommunication

using CommonLib.Communication.SerialPortCommunication;
using CommonLib.Timer;
using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CommonLib.Communication.SocketCommunication
{
    public abstract class SocketConnectionDeveice : IDeviceConnect, IDisposable
    {
        public virtual Action<string, byte[]> DataMonitor { get; set; }

        public virtual string ConnectState { get; set; } = "UnConnected";

        protected virtual SocketConnectionParameters ConnectionParameters { get; set; }

        /// <summary>
        /// 线程取消信号源对象
        /// </summary>
        protected virtual CancellationTokenSource CTS { get; set; }

        /// <summary>
        /// 初始线程取消信息源对象
        /// </summary>
        protected virtual void InitCTS()
        {
            if (CTS == null || CTS.IsCancellationRequested)
            {
                CTS = new CancellationTokenSource();
                //CTS.Token.Register(CancelCallBack);//线程取消回调函数
            }
        }

        /// <summary>
        /// Socket对象
        /// </summary>
        protected virtual Socket Socket { get; set; }

        /// <summary>
        /// 打开Socket连接
        /// </summary>
        /// <returns></returns>
        protected virtual bool OpenSocket()
        {
            if (this.Socket == null) return false;
            if (!this.Socket.Connected)
            {
                var result = this.Socket.BeginConnect(this.ConnectionParameters.IP, this.ConnectionParameters.Port, null, null);
                result.AsyncWaitHandle.WaitOne(2000);
                if (!result.IsCompleted)
                {
                    this.Socket.Close();
                }
            }
            return this.Socket.Connected;
        }

        public virtual void AbortSRBytes()
        {
            CTS.Cancel();
        }

        public virtual bool Connect()
        {
            InitSocket(ConnectionParameters.IP, ConnectionParameters.Port);
            return OpenSocket();
        }

        public virtual void Disconnect()
        {
            Socket?.Close();
            Socket = null;
        }

        public virtual void Dispose()
        {
            Disconnect();
        }

        public virtual void SetCommunicationParameters(IParameters parameters)
        {
            this.ConnectionParameters = parameters as SocketConnectionParameters;
            InitSocket(ConnectionParameters.IP, ConnectionParameters.Port);
        }

        public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout)
        {
            InitCTS();
            Exception err = null;
            var ls = Task.Run(async () =>
            {
                try
                {
                    if (!OpenSocket()) throw new Exception("Socket connect failed!");
                    if (sendBytes != null && sendBytes.Count > 0)
                    {
                        var data = sendBytes.ToArray();
                        this.Socket.Send(data);
                        DataMonitor?.Invoke("Send", data);//监听发送数据
                    }
                    if (readLength <= 0) return null;// 判断是否需要回读
                    if (readDelay > 0)
                    {
                        await Task.Delay(readDelay, CTS.Token);
                    }
                    this.Socket.ReceiveTimeout = readTimeout;
                    byte[] buff = new byte[1024];
                    int iRet = this.Socket.Receive(buff);
                    if (iRet == readLength)
                    {
                        var retData = buff.Take(iRet).ToArray();
                        DataMonitor?.Invoke("Receive", retData);//监听回读数据
                        return retData.ToList();
                    }
                    else
                    {
                        throw new Exception("Reading socket data timeout!");
                    }
                }
                catch (Exception ex)
                {
                    err = ex;
                    return null;
                }
            }, CTS.Token).Result;
            if (err != null) throw err;
            return ls;
        }

        public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout)
        {
            InitCTS();
            Exception err = null;
            var ls = Task.Run(async () =>
            {
                try
                {
                    if (!OpenSocket()) throw new Exception("Socket connect failed!");
                    if (sendBytes != null && sendBytes.Count > 0)
                    {
                        var data = sendBytes.ToArray();
                        this.Socket.Send(data);
                        DataMonitor?.Invoke("Send", data);//监听发送数据
                    }
                    if (readDelay > 0)
                    {
                        await Task.Delay(readDelay, CTS.Token);
                    }
                    this.Socket.ReceiveTimeout = readTimeout;
                    byte[] buff = new byte[1024];
                    int iRet = this.Socket.Receive(buff);
                    if (iRet > 0)
                    {
                        var retData = buff.Take(iRet).ToArray();
                        DataMonitor?.Invoke("Receive", retData);//监听回读数据
                        return retData.ToList();
                    }
                    else
                    {
                        throw new Exception("Reading socket data timeout!");
                    }
                }
                catch (Exception ex)
                {
                    err = ex;
                    return null;
                }
            }, CTS.Token).Result;
            if (err != null) throw err;
            return ls;
        }

        /// <summary>
        /// 初始化Socket对象
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <param name="port">端口</param>
        /// <param name="pt">socket支持的协议</param>
        protected virtual void InitSocket(string ip, int port, ProtocolType pt = ProtocolType.Tcp)
        {
            if (Socket != null && Socket.Connected) Socket.Close();
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, pt);
        }
    }
}



using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace CommonLib.Communication.SocketCommunication
{
    public class SocketConnectionParameters : ParametersBase, IParameters
    {
        public string IP => GetPropertyValue<string>();

        public int Port => GetPropertyValue<int>();

        protected T GetPropertyValue<T>([CallerMemberName] string properityName = "")
        {
            return GetValue<T>(properityName);
        }
    }
}

SerialPortCommunication

using CommonLib.LogUtils.Log4net;
using CommonLib.Timer;
using Prism.Common;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CommonLib.Communication.SerialPortCommunication
{
    /// <summary>
    /// 串口通讯设备基类
    /// </summary>
    public abstract class SerialPortConnectionDeveice : Log4Base, IDeviceConnect, IDisposable
    {
        public virtual Action<string, byte[]> DataMonitor { get; set; }

        public virtual string ConnectState { get; set; } = "UnConnected";

        /// <summary>
        /// 线程锁对象
        /// </summary>
        protected readonly object lockObj = new object();

        /// <summary>
        /// 线程取消信号源对象
        /// </summary>
        protected virtual CancellationTokenSource CTS { get; set; }

        /// <summary>
        /// 初始线程取消信息源对象
        /// </summary>
        protected virtual void InitCTS()
        {
            if (CTS == null || CTS.IsCancellationRequested)
            {
                CTS = new CancellationTokenSource();
                //CTS.Token.Register(CancelCallBack);//线程取消回调函数
            }
        }

        /// <summary>
        /// 串口对象
        /// </summary>
        protected virtual SerialPort ComPort { get; set; }

        /// <summary>
        /// 初始化串口
        /// </summary>
        /// <param name="portName">串口名称</param>
        /// <param name="baudRate">波特率</param>
        protected virtual void InitComPort(string portName, int baudRate)
        {
            if (ComPort != null)
            {
                if (ComPort.IsOpen) ComPort.Close();
                ComPort.PortName = portName;
                ComPort.BaudRate = baudRate;
            }
            else
            {
                ComPort = new SerialPort(portName, baudRate);
            }
        }

        protected virtual bool OpenComPort()
        {
            if (ComPort == null) return false;
            if (!ComPort.IsOpen) ComPort.Open();
            return ComPort.IsOpen;
        }

        protected virtual void ClosePort()
        {
            if (ComPort != null && ComPort.IsOpen) ComPort.Close();
        }

        public virtual void SetCommunicationParameters(IParameters parameters)
        {
            var objConnectionParameters = parameters as SerialPortConnectionParameters;
            if (objConnectionParameters.ContainsKey("SerialPort"))
            {
                this.ComPort = objConnectionParameters.GetValue<SerialPort>("SerialPort");
            }
            else
            {
                InitComPort(objConnectionParameters.PortName, objConnectionParameters.BaudRate);
            }
        }

        public virtual bool Connect()
        {
            return OpenComPort();
        }

        public virtual void Disconnect()
        {
            ClosePort();
        }

        public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout)
        {
            InitCTS();
            Exception err = null;
            var ls = Task.Run(() =>
            {
                try
                {
                    lock (lockObj)
                    {
                        if (!OpenComPort()) throw new Exception("Serial port opening failed!");
                        if (sendBytes != null && sendBytes.Count > 0)
                        {
                            var data = sendBytes.ToArray();
                            this.ComPort.Write(data, 0, data.Length);
                            DataMonitor?.Invoke("Send", data);//监听发送数据
                        }
                        if (readLength <= 0) return null;// 判断是否需要回读
                        if (readDelay > 0)
                        {
                            Task.Delay(readDelay, CTS.Token).Wait();
                        }
                        MyTimer timer = new MyTimer() { AbortFun = () => CTS.IsCancellationRequested };
                        var bRet = timer.WaitingBusinessTrue(() => this.ComPort.BytesToRead >= readLength, readTimeout);
                        if (bRet)
                        {
                            byte[] buff = new byte[readLength];
                            int iRet = this.ComPort.Read(buff, 0, buff.Length);
                            var retData = buff.Take(iRet).ToArray();
                            DataMonitor?.Invoke("Receive", retData);//监听回读数据
                            return retData.ToList();
                        }
                        else
                        {
                            throw new Exception("Reading serial port data timeout!");
                        }
                    }
                }
                catch (Exception ex)
                {
                    err = ex;
                    return null;
                }
            }, CTS.Token).Result;
            if (err != null) throw err;
            return ls;
        }

        public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout)
        {
            InitCTS();
            Exception err = null;
            var ls = Task.Run(() =>
            {
                try
                {
                    lock (lockObj)
                    {
                        if (!OpenComPort()) throw new Exception("Serial port opening failed!");
                        if (sendBytes != null && sendBytes.Count > 0)
                        {
                            var data = sendBytes.ToArray();
                            this.ComPort.Write(data, 0, data.Length);
                            DataMonitor?.Invoke("Send", data);//监听发送数据
                        }
                        if (readDelay > 0)
                        {
                            Task.Delay(readDelay, CTS.Token).Wait();
                        }
                        MyTimer timer = new MyTimer() { AbortFun = () => CTS.IsCancellationRequested };
                        var bRet = timer.WaitingBusinessTrue(() => this.ComPort.BytesToRead > 0, readTimeout);
                        if (bRet)
                        {
                            int buffBytesCount = this.ComPort.BytesToRead;
                            byte[] buff = new byte[buffBytesCount];
                            int iRet = this.ComPort.Read(buff, 0, buff.Length);
                            var retData = buff.Take(iRet).ToArray();
                            DataMonitor?.Invoke("Receive", retData);//监听回读数据
                            return retData.ToList();
                        }
                        else
                        {
                            throw new Exception("Reading serial port data timeout!");
                        }
                    }
                }
                catch (Exception ex)
                {
                    err = ex;
                    return null;
                }
            }, CTS.Token).Result;
            if (err != null) throw err;
            return ls;
        }

        public virtual void AbortSRBytes()
        {
            CTS.Cancel();
        }

        public virtual void Dispose()
        {
            Disconnect();
        }
    }
}


using Prism.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace CommonLib.Communication.SerialPortCommunication
{
    /// <summary>
    /// 串口通讯参数访问实现类
    /// </summary>
    public class SerialPortConnectionParameters : ParametersBase, IParameters
    {
        /// <summary>
        /// 串口名称
        /// </summary>
        public string PortName => GetPropertyValue<string>();

        public int BaudRate => GetPropertyValue<int>();

        protected T GetPropertyValue<T>([CallerMemberName] string properityName = "")
        {
            return GetValue<T>(properityName);
        }


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值