using SlnMesnac.Common; using SlnMesnac.Model.dto; using SlnMesnac.Model.Enum; using SlnMesnac.Serilog; using System; using System.Collections.Generic; using System.ComponentModel; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using TouchSocket.Core; using TouchSocket.Sockets; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- * 版权所有 (c) 2024 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 * 机器名称:LAPTOP-E0N2L34V * 命名空间:SlnMesnac.TouchSocket * 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82 * * 创建者:WenJY * 电子邮箱:wenjy@mesnac.com * 创建时间:2024-03-27 21:58:35 * 版本:V1.0.0 * 描述: * *-------------------------------------------------------------------- * 修改人: * 时间: * 修改说明: * * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> namespace SlnMesnac.TouchSocket { public class TcpServer { private SerilogHelper _logger; private readonly TcpService _service; /// /// 接收客户端指令委托 /// public delegate void ReceivedClientBuffer(byte[] buffer); public event ReceivedClientBuffer? ReceivedClientBufferEvent; public delegate void RefreshClientInfo(TcpService tcpService); public event RefreshClientInfo? RefreshClientInfoEvent; private StringChange _stringChange; public TcpServer(SerilogHelper logger, StringChange stringChange, TcpService tcpService) { _logger = logger; _service = tcpService; _stringChange = stringChange; } public void Init(int serverPort) { try { _service.Connecting = (client, e) => { _logger.Info($"客户端{client.IP}正在接入服务"); if (!client.IsClient) { e.Id = $"{client.IP}:{client.Port}"; } return EasyTask.CompletedTask; }; _service.Connected = (client, e) => { _logger.Info($"客户端{client.IP}接入服务成功"); RefreshClientInfoEvent?.Invoke(_service); return EasyTask.CompletedTask; }; _service.Closed = (client, e) => { _logger.Info($"客户端{client.IP}断开连接"); RefreshClientInfoEvent?.Invoke(_service); return EasyTask.CompletedTask; }; _service.Received = (client, e) => { //从客户端收到信息 //var mes = Encoding.UTF8.GetString(e.Memory.Span.ToArray(), 0, e.Memory.Span.Length);//注意:数据长度是byteBlock.Len byte[] receivedBuffer = new byte[e.Memory.Span.Length]; Array.Copy(e.Memory.Span.ToArray(), 0, receivedBuffer, 0, e.Memory.Span.Length); //MES客户端消息解析 if (receivedBuffer[4] == 0x65) { byte[] addrby = new byte[2]; Array.Copy(receivedBuffer, 1, addrby, 0, 2); var flag = BitConverter.ToUInt16(addrby, 0); _service.ResetIdAsync($"{client.IP}:{client.Port}", flag.ToString()); } //ReceivedClientBufferEvent?.Invoke(receivedBuffer); return EasyTask.CompletedTask; }; _service.SetupAsync(new TouchSocketConfig()//载入配置 .SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") }) .ConfigureContainer(a =>//容器的配置顺序应该在最前面 { a.AddConsoleLogger(); }) .ConfigurePlugins(a => { //自定义插件 })); _service.StartAsync(); _logger.Info($"TcpServer启动成功,监听端口:{serverPort}"); Task.Run(async delegate { //await Task.Delay(1000 * 20); SendHeartBeat(); }); } catch (Exception ex) { //throw new InvalidOperationException($"TcpServer启动异常:{ex.Message}"); _logger.Error($"TcpServer启动异常:{ex.Message}"); } } public byte DealMessage(byte[] bytes) { byte XOR = 0; try { byte[] datalen = new byte[bytes.Length - 8]; Array.Copy(bytes,4,datalen,0, bytes.Length - 8); string asciiStr = Encoding.ASCII.GetString(datalen); byte[] resultBytes = new byte[asciiStr.Length / 2]; for (int i = 0; i < asciiStr.Length / 2; i++) { int startIndex = i * 2; int length = Math.Min(2, asciiStr.Length - startIndex); string hexPair = asciiStr.Substring(startIndex, length); resultBytes[i] = Convert.ToByte(hexPair, 16); } XOR = CalculateVerify(resultBytes, resultBytes.Length); string sss = XOR.ToString("X2"); return XOR; } catch (Exception ex) { return XOR; } } public byte CalculateVerify(byte[] pMessage, int iLength) { UInt16 i; byte iVerify = 0; iVerify = pMessage[0]; for (i = 1; i < iLength; i++) { iVerify = (byte)(iVerify ^ pMessage[i]); } return iVerify; } public struct Heart { public Head head; public Tail tail; } public struct Head { public byte start; //起始 public byte[] addr; //软件地址 public byte mstaseq; //主站地址与命令序号 public byte control; //控制码 public byte[] length; //数据长度 } public struct Tail { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] verifica; //校验码 public byte end; //结束码 } /// /// 向所有客户端发送心跳 /// public void SendHeartBeat() { byte[] Heartbuf = new byte[10]; byte[] u16byte = new byte[2]; SoftMessagePack pMessagePackInfo = new SoftMessagePack(); pMessagePackInfo.iStationId = 1; pMessagePackInfo.iMsta = 0XF0 + 1; pMessagePackInfo.iLen = 0; pMessagePackInfo.iMessageType = (byte)MessageType.HeartPack_Type; while (true) { try { SendMessage(pMessagePackInfo); } catch (Exception ex) { _logger.Error($"SendHeartBeat异常:{ex.Message}"); } Thread.Sleep(1000 * 5 * 1); } } public async void SendMessage(SoftMessagePack pMessagePack) { UInt16 iPos = 0; byte[] u16byte = new byte[2]; try { byte[] SendBuffer = new byte[pMessagePack.iLen + 10]; SendBuffer[iPos] = pMessagePack.iSys; iPos += 1; u16byte = BitConverter.GetBytes(pMessagePack.iStationId); //站号 //u16byte = Swap16Bytes(u16byte); //协议里为大端在前 Array.Copy(u16byte, 0, SendBuffer, iPos, 2); iPos += 2; SendBuffer[iPos] = pMessagePack.iMsta; //主站地址 iPos += 1; SendBuffer[iPos] = pMessagePack.iMessageType; //帧类型 iPos += 1; u16byte = BitConverter.GetBytes(pMessagePack.iLen); //长度 //u16byte = Swap16Bytes(u16byte); //协议里为大端在前 Array.Copy(u16byte, 0, SendBuffer, iPos, 2); iPos += 2; if (pMessagePack.iLen > 0) { Array.Copy(pMessagePack.pMessage, 0, SendBuffer, iPos, pMessagePack.iLen); //数据域 iPos += (ushort)(pMessagePack.iLen); } u16byte = _stringChange.CalculateVerifytobyte(SendBuffer, pMessagePack.iLen + 7); //校验码 Array.Copy(u16byte, 0, SendBuffer, iPos, 2); iPos += 2; SendBuffer[iPos] = pMessagePack.iEndChar; //结束符1 iPos += 1; ReadOnlyMemory readOnlyMemory = new ReadOnlyMemory(SendBuffer); foreach (var item in _service.Clients) { #region Tcp服务器按目标Id先查找再回应 if (_service.Clients.TryGetClient(item.Id, out var tcpSessionClient)) { await tcpSessionClient.SendAsync(readOnlyMemory); } #endregion _logger.Info($"{pMessagePack.iStationId}发送原始报文{_stringChange.bytesToHexStr(SendBuffer, SendBuffer.Length)}"); } } catch (Exception ex) { _logger.Error($"SendMessage异常:{ex.Message}"); } } } }