Socket TCP

Demo


private readonly TcpHelper _tcpHelper;
public ctor()
{
    _tcpHelper = new TcpHelper();
    _tcpHelper.DataReceivedEvent += TcpClient_DataReceivedEvent;
    if (_tcpHelper.TcpInit("192.16.1.23", "6000"))
    {
        _tcpHelper.SetStartIdentifier(null);
        _tcpHelper.SetEndIdentifier(Encoding.UTF8.GetBytes("*"));
        
        var cmd = WSCommFunc.SerializeWithCamel(request);
        _tcpHelper.TcpSend(cmd);
    }
}


public void TcpClient_DataReceivedEvent(object sender, EventArgs e)
{
    if (e is CommTcpEventArgs args)
    {
        switch (args.State)
        {
            case CommTcpStateType.Open:
                {
                    ShowLogInfo("tcp已连接上.");
                }
                break;
            case CommTcpStateType.Error:
                {
                    ShowLogInfo("tcp发生错误! 信息:" + args.Message);
                }
                break;
            case CommTcpStateType.Close:
                {
                    ShowLogInfo("tcp已关闭.");
                }
                break;
            case CommTcpStateType.Connect:
                var message = Encoding.UTF8.GetString(args.Message);
                ShowLogInfo(message);        
                break;

            default:
                break;
        }
    }
}

TcpHelper

/// <summary>
/// Tcp通信帮助类(有帧头、帧尾检测)
/// </summary>
internal sealed class TcpHelper
{
    private readonly WeakEvent<EventArgs> _dataReceivedEvent = new WeakEvent<EventArgs>();

    /// <summary>
    /// 返回的消息数据弱事件
    /// </summary>
    public event EventHandler<EventArgs> DataReceivedEvent
    {
        add => _dataReceivedEvent.Add(value, value.Invoke);
        remove => _dataReceivedEvent.Remove(value);
    }

    public bool IsOpen => _client != null && _client.IsOpen;
    public string IP { get; set; }
    public string Port { get; set; }

    private CustomTcp _client;

    /// <summary>
    /// 帧头累加和,适用于 有帧头无帧尾
    /// </summary>
    private byte _startIdentifierSum;

    public TcpHelper()
    {
        _startIdentifierSum = 0;
    }

    /// <summary>
    /// 设置结尾标识符
    /// </summary>
    /// <param name="end"></param>
    public void SetEndIdentifier(byte[] end)
    {
        if (_client != null)
        {
            _client.EndIdentifier = end;
        }
    }

    /// <summary>
    /// 设置开始标识符
    /// </summary>
    /// <param name="start"></param>
    public void SetStartIdentifier(byte[] start)
    {
        if (_client != null)
        {
            _client.StartIdentifier = start;
            if (start == null)
            {
                _startIdentifierSum = 0;
            }
            else
            {
                _startIdentifierSum = WSCommFunc.GetSum(start);
            }
        }
    }

    /// <summary>
    /// Tcp初始化
    /// </summary>
    /// <param name="ip"></param>
    /// <param name="port"></param>
    public bool Init(string ip, string port)
    {
        IP = ip;
        Port = port;
        _client = new CustomTcp();
        _client.DataReceivedEvent += TcpClient_DataReceivedEvent;
        return _client.Open(ip, port);
    }

    /// <summary>
    /// 关闭连接
    /// </summary>
    public void Close()
    {
        if (_client != null)
        {
            _client.DataReceivedEvent -= TcpClient_DataReceivedEvent;
            _client.Close();
            _client = null;
        }
    }

    /// <summary>
    /// 发送命令
    /// </summary>
    /// <param name="cmd">命令内容</param>
    public void Send(string cmd)
    {
        if (_client != null)
        {
            try
            {
                _client.Send(cmd);
            }
            catch (Exception ex)
            {
                LogFactory.GetInstance().Error("tcp发送信息发生异常:", ex);
            }
        }
    }

    /// <summary>
    /// 发送命令
    /// </summary>
    /// <param name="data">命令内容</param>
    public void Send(byte[] data)
    {
        if (_client != null)
        {
            try
            {
                _client.Send(data);
            }
            catch (Exception ex)
            {
                LogFactory.GetInstance().Error("tcp发送信息发生异常:", ex);
            }
        }
    }

    /// <summary>
    /// 发送命令(带数据累加和校验,包含帧头)
    /// </summary>
    /// <param name="data"></param>
    /// <param name="identifier">功能码</param>
    public void SendSumCheckWithHead(byte[] data, ControllerIdentifiers identifier)
    {
        // 通信命令格式: 起始符(88) + 功能码 + 数据长度(mod 255) + 数据内容(DATA) + 数据校验(前面所有字节和)
        int len = data.Length % 255;
        int sum = _startIdentifierSum + (int)identifier + len + WSCommFunc.GetSum(data);
        List<byte> tmp = new List<byte>(data.Length + 3) { (byte)identifier, (byte)len };
        tmp.AddRange(data);
        tmp.Add((byte)sum);
        if (IsOpen)
        {
            _client.Send(tmp.ToArray());
        }
    }

    /// <summary>
    /// 获取的数据校验(带数据累加和校验,包含帧头)
    /// </summary>
    /// <param name=""></param>
    /// <returns>true校验成功</returns>
    public bool DataSumCheckWithHead(byte[] data)
    {
        // 数据格式: 功能码 + 数据长度(mod 255) + 数据内容(DATA) + 数据校验
        int length = data.Length;
        if (length <= 3)
        {
            return false;
        }
        // 长度不一致,异常数据
        if (data[1] != length - 3)
        {
            return false;
        }
        byte[] temp = new byte[length - 1];
        Array.Copy(data, 0, temp, 0, length - 1);
        byte sum = (byte)(_startIdentifierSum + WSCommFunc.GetSum(temp));
        return sum == data[length - 1];
    }

    private void TcpClient_DataReceivedEvent(object sender, EventArgs e)
    {
        _ = _dataReceivedEvent.Invoke(this, e);
    }
}

/// <summary>
/// 设备的功能码
/// </summary>
internal enum ControllerIdentifiers
{
    /// <summary>
    /// -, 返回0xA0
    /// </summary>
    [VersionData("A0")]
    心跳包 = 0xA0,

    /// <summary>
    /// 0xBB, 返回0xAB
    /// </summary>
    [VersionData("AB")]
    设置本地参数 = 0xBB,

    /// <summary>
    /// 0xBC, 返回0xAC
    /// </summary>
    [VersionData("AC")]
    读取本地参数 = 0xBC,
}

其中,CustomTcp是基于SuperSocket.ClientEngine的封装,可自行实现。

posted @   wesson2019  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示