using common.libs; using common.libs.extends; using System.Buffers; using System.Net; using System.Net.Sockets; namespace cmonitor.server.service { /// /// 连接对象 /// public interface IConnection { public string Name{ get; set; } /// /// /// 已连接 /// public bool Connected { get; } public IPEndPoint Address { get; } #region 接收数据 /// /// 请求数据包装对象 /// public MessageRequestWrap ReceiveRequestWrap { get; } /// /// 回复数据包装对象 /// public MessageResponseWrap ReceiveResponseWrap { get; } /// /// 接收到的原始数据 /// public Memory ReceiveData { get; set; } #endregion /// /// 发送 /// /// /// public Task Send(ReadOnlyMemory data, bool unconnectedMessage = false); /// /// 发送 /// /// /// /// public Task Send(byte[] data, int length, bool unconnectedMessage = false); /// /// 销毁 /// public void Disponse(); #region 回复消息相关 public Memory ResponseData { get; } public void Write(Memory data); public void Write(ulong num); public void Write(ushort num); public void Write(ushort[] nums); /// /// 英文多用这个 /// /// public void WriteUTF8(string str); /// /// 中文多用这个 /// /// public void WriteUTF16(string str); /// /// 归还池 /// public void Return(); #endregion public Task WaitOne(); public void Release(); } public abstract class Connection : IConnection { public Connection() { } public string Name { get; set; } /// /// 已连接 /// public virtual bool Connected => false; /// /// 地址 /// public IPEndPoint Address { get; protected set; } #region 接收数据 /// /// 接收请求数据 /// public MessageRequestWrap ReceiveRequestWrap { get; set; } /// /// 接收回执数据 /// public MessageResponseWrap ReceiveResponseWrap { get; set; } /// /// 接收数据 /// public Memory ReceiveData { get; set; } #endregion #region 回复数据 public Memory ResponseData { get; private set; } private byte[] responseData; private int length = 0; public void Write(Memory data) { ResponseData = data; } public void Write(ulong num) { length = 8; responseData = ArrayPool.Shared.Rent(length); num.ToBytes(responseData); ResponseData = responseData.AsMemory(0, length); } public void Write(ushort num) { length = 2; responseData = ArrayPool.Shared.Rent(length); num.ToBytes(responseData); ResponseData = responseData.AsMemory(0, length); } public void Write(ushort[] nums) { length = nums.Length * 2; responseData = ArrayPool.Shared.Rent(length); nums.ToBytes(responseData); ResponseData = responseData.AsMemory(0, length); } /// /// 英文多用这个 /// /// public void WriteUTF8(string str) { var span = str.AsSpan(); responseData = ArrayPool.Shared.Rent((span.Length + 1) * 3 + 8); var memory = responseData.AsMemory(); int utf8Length = span.ToUTF8Bytes(memory.Slice(8)); span.Length.ToBytes(memory); utf8Length.ToBytes(memory.Slice(4)); length = utf8Length + 8; ResponseData = responseData.AsMemory(0, length); } /// /// 中文多用这个 /// /// public void WriteUTF16(string str) { var span = str.GetUTF16Bytes(); length = span.Length + 4; responseData = ArrayPool.Shared.Rent(length); str.Length.ToBytes(responseData); span.CopyTo(responseData.AsSpan(4)); ResponseData = responseData.AsMemory(0, length); } /// /// 归还池 /// public void Return() { if (length > 0 && ResponseData.Length > 0) { ArrayPool.Shared.Return(responseData); } ResponseData = Helper.EmptyArray; responseData = null; length = 0; } #endregion /// /// 发送 /// /// /// public abstract Task Send(ReadOnlyMemory data, bool logger = false); /// /// 发送 /// /// /// /// public abstract Task Send(byte[] data, int length, bool logger = false); /// /// 销毁 /// public virtual void Disponse() { try { if (Semaphore != null) { if (locked) { locked = false; Semaphore.Release(); } Semaphore.Dispose(); } Semaphore = null; } catch (Exception ex) { Logger.Instance.Error(ex); } //ReceiveRequestWrap = null; //ReceiveResponseWrap = null; } SemaphoreSlim Semaphore = new SemaphoreSlim(1); bool locked = false; public virtual async Task WaitOne() { try { if (Semaphore != null) { locked = true; await Semaphore.WaitAsync(); } } catch (Exception ex) { Logger.Instance.Error(ex); } } public virtual void Release() { try { if (Semaphore != null) { locked = false; Semaphore.Release(); } } catch (Exception ex) { Logger.Instance.Error(ex); } } } public sealed class TcpConnection : Connection { public TcpConnection(Socket tcpSocket) : base() { TcpSocket = tcpSocket; IPEndPoint address = TcpSocket.RemoteEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0); if (address.Address.AddressFamily == AddressFamily.InterNetworkV6 && address.Address.IsIPv4MappedToIPv6) { address = new IPEndPoint(new IPAddress(address.Address.GetAddressBytes()[^4..]), address.Port); } Address = address; } /// /// 已连接 /// public override bool Connected => TcpSocket != null && TcpSocket.Connected; /// /// socket /// public Socket TcpSocket { get; private set; } /// /// 发送 /// /// /// public override async Task Send(ReadOnlyMemory data, bool unconnectedMessage = false) { if (Connected) { try { await TcpSocket.SendAsync(data, SocketFlags.None); //SentBytes += (ulong)data.Length; return true; } catch (Exception ex) { Disponse(); if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) Logger.Instance.Error(ex); } } return false; } /// /// 发送 /// /// /// /// public override async Task Send(byte[] data, int length, bool unconnectedMessage = false) { return await Send(data.AsMemory(0, length), unconnectedMessage); } /// /// 销毁 /// public override void Disponse() { base.Disponse(); if (TcpSocket != null) { TcpSocket.SafeClose(); TcpSocket.Dispose(); } } } }