using common.libs;
using common.libs.extends;
using System.Buffers;
using System.Net;
using System.Net.Sockets;
namespace cmonitor.server
{
///
/// 连接对象
///
public interface IConnection
{
public string Name { get; set; }
///
///
/// 已连接
///
public bool Connected { get; }
public IPEndPoint Address { get; }
public IPEndPoint LocalAddress { 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 abstract class Connection : IConnection
{
public Connection()
{
}
public string Name { get; set; }
///
/// 已连接
///
public virtual bool Connected => false;
///
/// 地址
///
public IPEndPoint Address { get; protected set; }
public IPEndPoint LocalAddress { 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()
{
}
}
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;
IPEndPoint localaddress = TcpSocket.LocalEndPoint as IPEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
if (localaddress.Address.AddressFamily == AddressFamily.InterNetworkV6 && localaddress.Address.IsIPv4MappedToIPv6)
{
localaddress = new IPEndPoint(new IPAddress(localaddress.Address.GetAddressBytes()[^4..]), localaddress.Port);
}
LocalAddress = localaddress;
}
///
/// 已连接
///
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();
}
}
}
}