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}");
}
}
}
}