You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
10 KiB
C#

4 weeks ago
using SlnMesnac.Common;
using SlnMesnac.Model.dto;
using SlnMesnac.Model.Enum;
using SlnMesnac.Serilog;
2 years ago
using System;
using System.Collections.Generic;
4 weeks ago
using System.ComponentModel;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
2 years ago
using System.Text;
using System.Threading;
using System.Threading.Tasks;
2 years ago
using TouchSocket.Core;
using TouchSocket.Sockets;
#region << 版 本 注 释 >>
4 weeks ago
2 years ago
/*--------------------------------------------------------------------
* (c) 2024 WenJY
* CLR4.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
*--------------------------------------------------------------------*/
4 weeks ago
2 years ago
#endregion << 版 本 注 释 >>
4 weeks ago
2 years ago
namespace SlnMesnac.TouchSocket
{
2 years ago
public class TcpServer
2 years ago
{
4 weeks ago
private SerilogHelper _logger;
2 years ago
private readonly TcpService _service;
4 weeks ago
2 years ago
/// <summary>
/// 接收客户端指令委托
/// </summary>
public delegate void ReceivedClientBuffer(byte[] buffer);
4 weeks ago
2 years ago
public event ReceivedClientBuffer? ReceivedClientBufferEvent;
public delegate void RefreshClientInfo(TcpService tcpService);
4 weeks ago
public event RefreshClientInfo? RefreshClientInfoEvent;
4 weeks ago
private StringChange _stringChange;
4 weeks ago
public TcpServer(SerilogHelper logger, StringChange stringChange, TcpService tcpService)
2 years ago
{
_logger = logger;
_service = tcpService;
4 weeks ago
_stringChange = stringChange;
}
2 years ago
public void Init(int serverPort)
2 years ago
{
try
{
_service.Connecting = (client, e) =>
{
4 weeks ago
_logger.Info($"客户端{client.IP}正在接入服务");
if (!client.IsClient)
{
e.Id = $"{client.IP}:{client.Port}";
}
2 years ago
return EasyTask.CompletedTask;
};
_service.Connected = (client, e) =>
{
4 weeks ago
_logger.Info($"客户端{client.IP}接入服务成功");
2 years ago
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
4 weeks ago
_service.Closed = (client, e) =>
{
4 weeks ago
_logger.Info($"客户端{client.IP}断开连接");
2 years ago
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
_service.Received = (client, e) =>
{
4 weeks ago
//从客户端收到信息
//var mes = Encoding.UTF8.GetString(e.Memory.Span.ToArray(), 0, e.Memory.Span.Length);//注意数据长度是byteBlock.Len
4 weeks ago
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)
{
4 weeks ago
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());
}
4 weeks ago
//ReceivedClientBufferEvent?.Invoke(receivedBuffer);
2 years ago
return EasyTask.CompletedTask;
};
4 weeks ago
_service.SetupAsync(new TouchSocketConfig()//载入配置
.SetListenIPHosts(new IPHost[] { new IPHost($"0.0.0.0:{serverPort}") })
2 years ago
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
//自定义插件
}));
4 weeks ago
_service.StartAsync();
_logger.Info($"TcpServer启动成功监听端口{serverPort}");
Task.Run(async delegate
{
//await Task.Delay(1000 * 20);
SendHeartBeat();
});
2 years ago
}
catch (Exception ex)
{
//throw new InvalidOperationException($"TcpServer启动异常{ex.Message}");
4 weeks ago
_logger.Error($"TcpServer启动异常{ex.Message}");
2 years ago
}
}
4 weeks ago
public byte DealMessage(byte[] bytes)
{
4 weeks ago
byte XOR = 0;
try
{
4 weeks ago
byte[] datalen = new byte[bytes.Length - 8];
Array.Copy(bytes,4,datalen,0, bytes.Length - 8);
string asciiStr = Encoding.ASCII.GetString(datalen);
4 weeks ago
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;
}
4 weeks ago
catch (Exception ex)
{
4 weeks ago
return XOR;
}
}
4 weeks ago
public byte CalculateVerify(byte[] pMessage, int iLength)
{
4 weeks ago
UInt16 i;
byte iVerify = 0;
4 weeks ago
iVerify = pMessage[0];
for (i = 1; i < iLength; i++)
{
4 weeks ago
iVerify = (byte)(iVerify ^ pMessage[i]);
}
4 weeks ago
return iVerify;
}
4 weeks ago
public struct Heart
{
4 weeks ago
public Head head;
public Tail tail;
}
4 weeks ago
public struct Head
{
4 weeks ago
public byte start; //起始
public byte[] addr; //软件地址
public byte mstaseq; //主站地址与命令序号
public byte control; //控制码
public byte[] length; //数据长度
}
4 weeks ago
public struct Tail
{
4 weeks ago
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] verifica; //校验码
public byte end; //结束码
}
/// <summary>
4 weeks ago
/// 向所有客户端发送心跳
/// </summary>
4 weeks ago
public void SendHeartBeat()
{
4 weeks ago
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}");
4 weeks ago
}
Thread.Sleep(1000 * 5 * 1);
}
}
4 weeks ago
public async void SendMessage(SoftMessagePack pMessagePack)
{
4 weeks ago
UInt16 iPos = 0;
byte[] u16byte = new byte[2];
try
{
byte[] SendBuffer = new byte[pMessagePack.iLen + 10];
SendBuffer[iPos] = pMessagePack.iSys;
iPos += 1;
4 weeks ago
u16byte = BitConverter.GetBytes(pMessagePack.iStationId); //站号
//u16byte = Swap16Bytes(u16byte); //协议里为大端在前
Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
iPos += 2;
4 weeks ago
SendBuffer[iPos] = pMessagePack.iMsta; //主站地址
iPos += 1;
4 weeks ago
SendBuffer[iPos] = pMessagePack.iMessageType; //帧类型
iPos += 1;
4 weeks ago
u16byte = BitConverter.GetBytes(pMessagePack.iLen); //长度
//u16byte = Swap16Bytes(u16byte); //协议里为大端在前
Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
iPos += 2;
4 weeks ago
if (pMessagePack.iLen > 0)
{
Array.Copy(pMessagePack.pMessage, 0, SendBuffer, iPos, pMessagePack.iLen); //数据域
iPos += (ushort)(pMessagePack.iLen);
}
4 weeks ago
u16byte = _stringChange.CalculateVerifytobyte(SendBuffer, pMessagePack.iLen + 7); //校验码
4 weeks ago
Array.Copy(u16byte, 0, SendBuffer, iPos, 2);
iPos += 2;
4 weeks ago
SendBuffer[iPos] = pMessagePack.iEndChar; //结束符1
iPos += 1;
4 weeks ago
ReadOnlyMemory<byte> readOnlyMemory = new ReadOnlyMemory<byte>(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}");
4 weeks ago
}
}
2 years ago
}
4 weeks ago
}