客户端网络库(包括.netstandard2.0)优化 消灭GC,复用ArrayPool<byte>

This commit is contained in:
sin365 2025-11-06 15:51:15 +08:00
parent 67f9c51d6f
commit 2eef9aa0d1
10 changed files with 446 additions and 87 deletions

View File

@ -1,8 +1,75 @@
using System.Net.Sockets;
using System.Buffers;
using System.Net.Sockets;
namespace HaoYueNet.ClientNetwork
{
public static class BytesArrayPool
{
public static byte[] RentBuffer(int minSize)
{
return ArrayPool<byte>.Shared.Rent(minSize);
}
public static void ReturnBuffer(byte[] buffer)
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
public static class BaseData
{
#if NETSTANDARD2_0_OR_GREATER
static class BitConverter
{
/// <summary>
/// 将short值以小端序写入字节数组
/// </summary>
/// <param name="buffer">目标字节数组</param>
/// <param name="value">要写入的short值</param>
/// <param name="offset">写入起始位置</param>
public static void TryWriteBytes(byte[] buffer, short value, int offset = 0)
{
// 小端序:低位在前,高位在后
buffer[offset] = (byte)value; // 低位字节
buffer[offset + 1] = (byte)(value >> 8); // 高位字节
}
/// <summary>
/// 将ushort值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, ushort value, int offset = 0)
{
buffer[offset] = (byte)value; // 低位字节
buffer[offset + 1] = (byte)(value >> 8); // 高位字节
}
/// <summary>
/// 将uint值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, uint value, int offset = 0)
{
buffer[offset] = (byte)value; // 字节0 (最低位)
buffer[offset + 1] = (byte)(value >> 8); // 字节1
buffer[offset + 2] = (byte)(value >> 16); // 字节2
buffer[offset + 3] = (byte)(value >> 24); // 字节3 (最高位)
}
/// <summary>
/// 将int值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, int value, int offset = 0)
{
buffer[offset] = (byte)value; // 字节0 (最低位)
buffer[offset + 1] = (byte)(value >> 8); // 字节1
buffer[offset + 2] = (byte)(value >> 16); // 字节2
buffer[offset + 3] = (byte)(value >> 24); // 字节3 (最高位)
}
public static ushort ToUInt16(Span<byte> span)
{
return System.BitConverter.ToUInt16(span.ToArray(), 0);
}
}
#endif
/// <summary>
/// 心跳包数据
/// </summary>
@ -16,12 +83,52 @@ namespace HaoYueNet.ClientNetwork
}
public static class HunterNet_S2C
{
const int LenghtDataLength = sizeof(UInt32);
const int CmdDataLength = sizeof(UInt16);
const int ErrDataLength = sizeof(UInt16);
public static int GetAllLength(byte[] bodyData)
{
return CmdDataLength + ErrDataLength + LenghtDataLength + bodyData.Length;
}
public static int GetBodyLength(byte[] allData)
{
return allData.Length - CmdDataLength - ErrDataLength;
}
public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs, UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data)
{
myreadEventArgs.SetBuffer(CreatePkgData(CmdID, Error, AddonBytes_Data));
int allDataLength = GetAllLength(AddonBytes_Data);
byte[] finalData = BytesArrayPool.RentBuffer(allDataLength);
CreatePkgData(CmdID, Error, AddonBytes_Data, ref finalData, out int usefulLenght);
myreadEventArgs.SetBuffer(finalData, 0, usefulLenght);
BytesArrayPool.ReturnBuffer(finalData);
//myreadEventArgs.SetBuffer(CreatePkgData(CmdID, Error, AddonBytes_Data));
}
public static byte[] CreatePkgData(UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data)
public static void CreatePkgData(UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data, ref byte[] finalData, out int usefulLenght)
{
int allLength = GetAllLength(AddonBytes_Data);
byte[] bytes_allLenght = BytesArrayPool.RentBuffer(LenghtDataLength);
BitConverter.TryWriteBytes(bytes_allLenght, allLength);//包长度
byte[] bytes_cmdid = BytesArrayPool.RentBuffer(CmdDataLength);
BitConverter.TryWriteBytes(bytes_cmdid, CmdID);
byte[] bytes_errid = BytesArrayPool.RentBuffer(ErrDataLength);
BitConverter.TryWriteBytes(bytes_errid, Error);
Buffer.BlockCopy(bytes_allLenght, 0, finalData, 0, LenghtDataLength);
//CMDID
Buffer.BlockCopy(bytes_cmdid, 0, finalData, LenghtDataLength, CmdDataLength);
//ErrID
Buffer.BlockCopy(bytes_errid, 0, finalData, LenghtDataLength + CmdDataLength, ErrDataLength);
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, finalData, LenghtDataLength + CmdDataLength + ErrDataLength, AddonBytes_Data.Length);
BytesArrayPool.ReturnBuffer(bytes_allLenght);
BytesArrayPool.ReturnBuffer(bytes_cmdid);
BytesArrayPool.ReturnBuffer(bytes_errid);
usefulLenght = allLength;
/*
//包长度
int AllLenght = 4 + 2 + 2 + AddonBytes_Data.Length;
byte[] BufferData = new byte[AllLenght];
@ -33,7 +140,7 @@ namespace HaoYueNet.ClientNetwork
Buffer.BlockCopy(BitConverter.GetBytes(Error), 0, BufferData, 4 + 2, sizeof(UInt16));
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, 4 + 2 + 2, AddonBytes_Data.Length);
return BufferData;
return BufferData;*/
}
public static void AnalysisPkgData(Span<byte> srcdata, out UInt16 CmdID, out UInt16 Error, out byte[] data)
{
@ -44,12 +151,57 @@ namespace HaoYueNet.ClientNetwork
}
public static class HunterNet_C2S
{
const int LenghtDataLength = sizeof(UInt32);
const int CmdDataLength = sizeof(UInt16);
public static int GetAllLengthByBody(byte[] bodyData)
{
return LenghtDataLength + CmdDataLength + bodyData.Length;
}
public static int GetAllLengthByUsedLen(int UsedLength)
{
return LenghtDataLength + CmdDataLength + UsedLength;
}
public static int GetBodyLength(byte[] allData)
{
return allData.Length - CmdDataLength;
}
public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs, UInt16 CmdID, byte[] AddonBytes_Data)
{
myreadEventArgs.SetBuffer(CreatePkgData(CmdID, AddonBytes_Data));
int allDataLength = GetAllLengthByBody(AddonBytes_Data);
byte[] finalData = BytesArrayPool.RentBuffer(allDataLength);
CreatePkgData(CmdID, AddonBytes_Data, ref finalData, out int usefulLenght);
myreadEventArgs.SetBuffer(finalData, 0, usefulLenght);
BytesArrayPool.ReturnBuffer(finalData);
//myreadEventArgs.SetBuffer(CreatePkgData(CmdID, AddonBytes_Data));
}
public static byte[] CreatePkgData(UInt16 CmdID, byte[] AddonBytes_Data)
public static void CreatePkgData(UInt16 CmdID, byte[] bytesdata, ref byte[] finalData, out int usefulLenght)
{
CreatePkgData(CmdID, bytesdata, bytesdata.Length, ref finalData, out usefulLenght);
}
public static void CreatePkgData(UInt16 CmdID, byte[] bytesdata, int bytesdata_useLenght, ref byte[] finalData, out int usefulLenght)
{
int allLength = GetAllLengthByUsedLen(bytesdata_useLenght);
byte[] bytes_allLenght = BytesArrayPool.RentBuffer(LenghtDataLength);
BitConverter.TryWriteBytes(bytes_allLenght, allLength);
byte[] bytes_cmdid = BytesArrayPool.RentBuffer(CmdDataLength);
BitConverter.TryWriteBytes(bytes_cmdid, CmdID);
//包长度
Buffer.BlockCopy(bytes_allLenght, 0, finalData, 0, LenghtDataLength);
//CMDID
Buffer.BlockCopy(bytes_cmdid, 0, finalData, LenghtDataLength, CmdDataLength);
//DATA
Buffer.BlockCopy(bytesdata, 0, finalData, LenghtDataLength + CmdDataLength, bytesdata_useLenght);
BytesArrayPool.ReturnBuffer(bytes_allLenght);
BytesArrayPool.ReturnBuffer(bytes_cmdid);
usefulLenght = allLength;
/*
byte[] AddonBytes_CmdID = BitConverter.GetBytes(CmdID);
int AllLenght = AddonBytes_CmdID.Length + AddonBytes_Data.Length + 4;
//包长度
@ -61,7 +213,7 @@ namespace HaoYueNet.ClientNetwork
Buffer.BlockCopy(AddonBytes_CmdID, 0, BufferData, 4, AddonBytes_CmdID.Length);
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, 4 + 2, AddonBytes_Data.Length);
return BufferData;
return BufferData;*/
}
public static void AnalysisPkgData(Span<byte> srcdata, out UInt16 CmdID, out byte[] data)

View File

@ -380,14 +380,14 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
long FristBeginPos = token.memoryStream.Position;
//从Byte池申请
byte[] lenBytes = ArrayPool<byte>.Shared.Rent(4);
byte[] lenBytes = BytesArrayPool.RentBuffer(4);
token.memoryStream.Seek(0, SeekOrigin.Begin);
token.memoryStream.Read(lenBytes, 0, 4);
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
//归还byte[]
ArrayPool<byte>.Shared.Return(lenBytes);
BytesArrayPool.ReturnBuffer(lenBytes);
if (packageLen > token.memoryStream.Length - 4)
{
@ -396,7 +396,7 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
}
//申请byte池 一定要记得回收!!
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(packageLen);
byte[] rev_fromArrayPool = BytesArrayPool.RentBuffer(packageLen);
token.memoryStream.Seek(4, SeekOrigin.Begin);
token.memoryStream.Read(rev_fromArrayPool, 0, packageLen);
@ -416,7 +416,7 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
DataCallBackReady(token, rev_span);
//回收这里依赖DataCallBackReady中有一次数据拷贝这个后续还要进一步精进性能优化否则不能在这里回收否则影响业务层
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
} while (token.memoryStream.Length > 4);
}

View File

@ -22,9 +22,9 @@ namespace HaoYueNet.ClientNetwork
private static int MaxSendIndexNum = 3;
//响应倒计时计数
private static int RevIndex=0;
private static int RevIndex = 0;
//发送倒计时计数
private static int SendIndex=0;
private static int SendIndex = 0;
//计时器间隔
private static int TimerInterval = 3000;
@ -35,7 +35,7 @@ namespace HaoYueNet.ClientNetwork
public static int LastConnectPort;
public bool bDetailedLog = false;
public bool Init(string IP, int port,bool isHadDetailedLog = true, bool bBindReuseAddress = false,int bBindport = 0,AddressFamily addressFamily = AddressFamily.InterNetwork)
public bool Init(string IP, int port, bool isHadDetailedLog = true, bool bBindReuseAddress = false, int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
LogOut("==>初始化网络核心");
@ -60,7 +60,7 @@ namespace HaoYueNet.ClientNetwork
//带回调的
try
{
if(bDetailedLog)
if (bDetailedLog)
LogOut("连接到远程IP " + IP + ":" + port);
else
LogOut("连接到远程服务");
@ -108,13 +108,13 @@ namespace HaoYueNet.ClientNetwork
client.Close();
}
private void SendToSocket(byte[] data)
private void SendToSocket(byte[] data, int usefulLenght)
{
//已拼接包长度,这里不再需要拼接长度
//data = SendDataWithHead(data);
try
{
SendWithIndex(data);
SendWithIndex(data, usefulLenght);
}
catch (Exception ex)
{
@ -129,7 +129,7 @@ namespace HaoYueNet.ClientNetwork
{
try
{
SendWithIndex(HeartbeatData);
SendWithIndex(HeartbeatData, HeartbeatData.Length);
}
catch (Exception ex)
{
@ -145,14 +145,14 @@ namespace HaoYueNet.ClientNetwork
/// 发送数据并计数
/// </summary>
/// <param name="data"></param>
private void SendWithIndex(byte[] data)
private void SendWithIndex(byte[] data, int usefulLenght)
{
lock (sendLock)
{
//增加发送计数
SendIndex = MaxSendIndexNum;
//发送数据
client.Send(data);
client.Send(data, usefulLenght, SocketFlags.None);
}
}
@ -161,10 +161,32 @@ namespace HaoYueNet.ClientNetwork
/// </summary>
/// <param name="CMDID"></param>
/// <param name="data">序列化之后的数据</param>
public void SendToServer(int CMDID,byte[] data)
public virtual void SendToServer(int CmdID, byte[] data)
{
byte[] _finaldata = HunterNet_C2S.CreatePkgData((ushort)CMDID, data);
SendToSocket(_finaldata);
SendToServerWithLength(CmdID, ref data, data.Length);
//int allDataLength = HunterNet_C2S.GetAllLengthByBody(data);
//byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
//HunterNet_C2S.CreatePkgData((ushort)CmdID, data, ref _finaldata, out int usefulLenght);
//SendToSocket(_finaldata, usefulLenght);
//BytesArrayPool.ReturnBuffer(_finaldata);
//byte[] _finaldata = HunterNet_C2S.CreatePkgData((ushort)CmdID, data);
//SendToSocket(_finaldata);
}
/// <summary>
/// 供外部调用 发送消息
/// </summary>
/// <param name="CMDID"></param>
/// <param name="data">序列化之后的数据</param>
public virtual void SendToServerWithLength(int CmdID, ref byte[] data, int len)
{
int allDataLength = HunterNet_C2S.GetAllLengthByUsedLen(len);
byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
HunterNet_C2S.CreatePkgData((ushort)CmdID, data, len, ref _finaldata, out int usefulLenght);
SendToSocket(_finaldata, usefulLenght);
BytesArrayPool.ReturnBuffer(_finaldata);
}
#region
@ -244,7 +266,7 @@ namespace HaoYueNet.ClientNetwork
return;
}
}
catch(Exception ex)
catch (Exception ex)
{
//清理数据
reciveMemoryStream.SetLength(0);

View File

@ -15,22 +15,22 @@ namespace HaoYueNet.ClientNetwork
private static int MaxSendIndexNum = 3;
//响应倒计时计数
private static int RevIndex=0;
private static int RevIndex = 0;
//发送倒计时计数
private static int SendIndex=0;
private static int SendIndex = 0;
//计时器间隔
private static int TimerInterval = 3000;
private System.Timers.Timer _heartTimer;
public void Init(bool bBindReuseAddress = false,int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
public void Init(bool bBindReuseAddress = false, int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
LogOut("==>初始化网络核心");
RevIndex = MaxRevIndexNum;
SendIndex = MaxSendIndexNum;
client = new Socket(addressFamily,SocketType.Stream, ProtocolType.Tcp);
client = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
if (bBindReuseAddress)
{
client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@ -78,13 +78,13 @@ namespace HaoYueNet.ClientNetwork
client.Close();
}
private void SendToSocket(byte[] data)
private void SendToSocket(byte[] data, int usefulLenght)
{
//已拼接包长度,这里不再需要拼接长度
//data = SendDataWithHead(data);
try
{
SendWithIndex(data);
SendWithIndex(data, usefulLenght);
}
catch (Exception ex)
{
@ -99,7 +99,7 @@ namespace HaoYueNet.ClientNetwork
{
try
{
SendWithIndex(BaseData.HeartbeatData);
SendWithIndex(BaseData.HeartbeatData, BaseData.HeartbeatData.Length);
}
catch (Exception ex)
{
@ -114,12 +114,12 @@ namespace HaoYueNet.ClientNetwork
/// 发送数据并计数
/// </summary>
/// <param name="data"></param>
private void SendWithIndex(byte[] data)
private void SendWithIndex(byte[] data, int usefulLenght)
{
//增加发送计数
SendIndex = MaxSendIndexNum;
//发送数据
client.Send(data);
client.Send(data, usefulLenght, SocketFlags.None);
}
/// <summary>
@ -130,8 +130,15 @@ namespace HaoYueNet.ClientNetwork
/// <param name="data"></param>
public void SendToSocket(int CMDID, int ERRCODE, byte[] data)
{
byte[] _finaldata = HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data);
SendToSocket(_finaldata);
int allDataLength = HunterNet_C2S.GetAllLengthByBody(data);
byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data, ref _finaldata, out int usefulLenght);
SendToSocket(_finaldata, usefulLenght);
BytesArrayPool.ReturnBuffer(_finaldata);
//byte[] _finaldata = HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data);
//SendToSocket(_finaldata);
}
public delegate void OnDataCallBack_Data(int CMDID, int ERRCODE, byte[] data);

View File

@ -199,7 +199,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
while (true)
{
//申请byte池 一定要记得回收!!
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(1024 * 1024 * 2);
byte[] rev_fromArrayPool = BytesArrayPool.RentBuffer(1024 * 1024 * 2);
int effective = 0;
try
@ -213,7 +213,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
//远程主机强迫关闭了一个现有的连接
OnCloseReady(client);
//回收
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
return;
}
}
@ -232,7 +232,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
reciveMemoryStream.Write(rev_fromArrayPool, 0, effective);//将接受到的数据写入内存流中
//回收
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
DataCallBackReady(client, reciveMemoryStream.ToArray());
//流复用的方式 不用重新new申请

View File

@ -1,9 +1,76 @@
using System;
using System.Buffers;
using System.Net.Sockets;
namespace HaoYueNet.ClientNetwork
{
public static class BytesArrayPool
{
public static byte[] RentBuffer(int minSize)
{
return ArrayPool<byte>.Shared.Rent(minSize);
}
public static void ReturnBuffer(byte[] buffer)
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
public static class BaseData
{
#if NETSTANDARD2_0_OR_GREATER
static class BitConverter
{
/// <summary>
/// 将short值以小端序写入字节数组
/// </summary>
/// <param name="buffer">目标字节数组</param>
/// <param name="value">要写入的short值</param>
/// <param name="offset">写入起始位置</param>
public static void TryWriteBytes(byte[] buffer, short value, int offset = 0)
{
// 小端序:低位在前,高位在后
buffer[offset] = (byte)value; // 低位字节
buffer[offset + 1] = (byte)(value >> 8); // 高位字节
}
/// <summary>
/// 将ushort值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, ushort value, int offset = 0)
{
buffer[offset] = (byte)value; // 低位字节
buffer[offset + 1] = (byte)(value >> 8); // 高位字节
}
/// <summary>
/// 将uint值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, uint value, int offset = 0)
{
buffer[offset] = (byte)value; // 字节0 (最低位)
buffer[offset + 1] = (byte)(value >> 8); // 字节1
buffer[offset + 2] = (byte)(value >> 16); // 字节2
buffer[offset + 3] = (byte)(value >> 24); // 字节3 (最高位)
}
/// <summary>
/// 将int值以小端序写入字节数组
/// </summary>
public static void TryWriteBytes(byte[] buffer, int value, int offset = 0)
{
buffer[offset] = (byte)value; // 字节0 (最低位)
buffer[offset + 1] = (byte)(value >> 8); // 字节1
buffer[offset + 2] = (byte)(value >> 16); // 字节2
buffer[offset + 3] = (byte)(value >> 24); // 字节3 (最高位)
}
public static ushort ToUInt16(Span<byte> span)
{
return System.BitConverter.ToUInt16(span.ToArray(), 0);
}
}
#endif
/// <summary>
/// 心跳包数据
/// </summary>
@ -17,13 +84,52 @@ namespace HaoYueNet.ClientNetwork
}
public static class HunterNet_S2C
{
const int LenghtDataLength = sizeof(UInt32);
const int CmdDataLength = sizeof(UInt16);
const int ErrDataLength = sizeof(UInt16);
public static int GetAllLength(byte[] bodyData)
{
return CmdDataLength + ErrDataLength + LenghtDataLength + bodyData.Length;
}
public static int GetBodyLength(byte[] allData)
{
return allData.Length - CmdDataLength - ErrDataLength;
}
public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs, UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data)
{
byte[] data = CreatePkgData(CmdID, Error, AddonBytes_Data);
myreadEventArgs.SetBuffer(data,0,data.Length);
int allDataLength = GetAllLength(AddonBytes_Data);
byte[] finalData = BytesArrayPool.RentBuffer(allDataLength);
CreatePkgData(CmdID, Error, AddonBytes_Data, ref finalData, out int usefulLenght);
myreadEventArgs.SetBuffer(finalData, 0, usefulLenght);
BytesArrayPool.ReturnBuffer(finalData);
//myreadEventArgs.SetBuffer(CreatePkgData(CmdID, Error, AddonBytes_Data));
}
public static byte[] CreatePkgData(UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data)
public static void CreatePkgData(UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data, ref byte[] finalData, out int usefulLenght)
{
int allLength = GetAllLength(AddonBytes_Data);
byte[] bytes_allLenght = BytesArrayPool.RentBuffer(LenghtDataLength);
BitConverter.TryWriteBytes(bytes_allLenght, allLength);//包长度
byte[] bytes_cmdid = BytesArrayPool.RentBuffer(CmdDataLength);
BitConverter.TryWriteBytes(bytes_cmdid, CmdID);
byte[] bytes_errid = BytesArrayPool.RentBuffer(ErrDataLength);
BitConverter.TryWriteBytes(bytes_errid, Error);
Buffer.BlockCopy(bytes_allLenght, 0, finalData, 0, LenghtDataLength);
//CMDID
Buffer.BlockCopy(bytes_cmdid, 0, finalData, LenghtDataLength, CmdDataLength);
//ErrID
Buffer.BlockCopy(bytes_errid, 0, finalData, LenghtDataLength + CmdDataLength, ErrDataLength);
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, finalData, LenghtDataLength + CmdDataLength + ErrDataLength, AddonBytes_Data.Length);
BytesArrayPool.ReturnBuffer(bytes_allLenght);
BytesArrayPool.ReturnBuffer(bytes_cmdid);
BytesArrayPool.ReturnBuffer(bytes_errid);
usefulLenght = allLength;
/*
//包长度
int AllLenght = 4 + 2 + 2 + AddonBytes_Data.Length;
byte[] BufferData = new byte[AllLenght];
@ -35,24 +141,68 @@ namespace HaoYueNet.ClientNetwork
Buffer.BlockCopy(BitConverter.GetBytes(Error), 0, BufferData, 4 + 2, sizeof(UInt16));
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, 4 + 2 + 2, AddonBytes_Data.Length);
return BufferData;
return BufferData;*/
}
public static void AnalysisPkgData(Span<byte> srcdata, out UInt16 CmdID, out UInt16 Error, out byte[] data)
{
CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2).ToArray(), 0);
Error = BitConverter.ToUInt16(srcdata.Slice(2, 2).ToArray(), 0);
CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2));
Error = BitConverter.ToUInt16(srcdata.Slice(2, 2));
data = srcdata.Slice(2 + 2).ToArray();
}
}
public static class HunterNet_C2S
{
const int LenghtDataLength = sizeof(UInt32);
const int CmdDataLength = sizeof(UInt16);
public static int GetAllLengthByBody(byte[] bodyData)
{
return LenghtDataLength + CmdDataLength + bodyData.Length;
}
public static int GetAllLengthByUsedLen(int UsedLength)
{
return LenghtDataLength + CmdDataLength + UsedLength;
}
public static int GetBodyLength(byte[] allData)
{
return allData.Length - CmdDataLength;
}
public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs, UInt16 CmdID, byte[] AddonBytes_Data)
{
byte[] data = CreatePkgData(CmdID, AddonBytes_Data);
myreadEventArgs.SetBuffer(data, 0, data.Length);
int allDataLength = GetAllLengthByBody(AddonBytes_Data);
byte[] finalData = BytesArrayPool.RentBuffer(allDataLength);
CreatePkgData(CmdID, AddonBytes_Data, ref finalData, out int usefulLenght);
myreadEventArgs.SetBuffer(finalData, 0, usefulLenght);
BytesArrayPool.ReturnBuffer(finalData);
//myreadEventArgs.SetBuffer(CreatePkgData(CmdID, AddonBytes_Data));
}
public static byte[] CreatePkgData(UInt16 CmdID, byte[] AddonBytes_Data)
public static void CreatePkgData(UInt16 CmdID, byte[] bytesdata, ref byte[] finalData, out int usefulLenght)
{
CreatePkgData(CmdID, bytesdata, bytesdata.Length, ref finalData, out usefulLenght);
}
public static void CreatePkgData(UInt16 CmdID, byte[] bytesdata,int bytesdata_useLenght, ref byte[] finalData, out int usefulLenght)
{
int allLength = GetAllLengthByUsedLen(bytesdata_useLenght);
byte[] bytes_allLenght = BytesArrayPool.RentBuffer(LenghtDataLength);
BitConverter.TryWriteBytes(bytes_allLenght, allLength);
byte[] bytes_cmdid = BytesArrayPool.RentBuffer(CmdDataLength);
BitConverter.TryWriteBytes(bytes_cmdid, CmdID);
//包长度
Buffer.BlockCopy(bytes_allLenght, 0, finalData, 0, LenghtDataLength);
//CMDID
Buffer.BlockCopy(bytes_cmdid, 0, finalData, LenghtDataLength, CmdDataLength);
//DATA
Buffer.BlockCopy(bytesdata, 0, finalData, LenghtDataLength + CmdDataLength, bytesdata_useLenght);
BytesArrayPool.ReturnBuffer(bytes_allLenght);
BytesArrayPool.ReturnBuffer(bytes_cmdid);
usefulLenght = allLength;
/*
byte[] AddonBytes_CmdID = BitConverter.GetBytes(CmdID);
int AllLenght = AddonBytes_CmdID.Length + AddonBytes_Data.Length + 4;
//包长度
@ -64,12 +214,12 @@ namespace HaoYueNet.ClientNetwork
Buffer.BlockCopy(AddonBytes_CmdID, 0, BufferData, 4, AddonBytes_CmdID.Length);
//DATA
Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, 4 + 2, AddonBytes_Data.Length);
return BufferData;
return BufferData;*/
}
public static void AnalysisPkgData(Span<byte> srcdata, out UInt16 CmdID, out byte[] data)
{
CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2).ToArray(),0);
CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2));
data = srcdata.Slice(2).ToArray();
}
}

View File

@ -383,14 +383,14 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
long FristBeginPos = token.memoryStream.Position;
//从Byte池申请
byte[] lenBytes = ArrayPool<byte>.Shared.Rent(4);
byte[] lenBytes = BytesArrayPool.RentBuffer(4);
token.memoryStream.Seek(0, SeekOrigin.Begin);
token.memoryStream.Read(lenBytes, 0, 4);
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
//归还byte[]
ArrayPool<byte>.Shared.Return(lenBytes);
BytesArrayPool.ReturnBuffer(lenBytes);
if (packageLen > token.memoryStream.Length - 4)
{
@ -399,7 +399,7 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
}
//申请byte池 一定要记得回收!!
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(packageLen);
byte[] rev_fromArrayPool = BytesArrayPool.RentBuffer(packageLen);
token.memoryStream.Seek(4, SeekOrigin.Begin);
token.memoryStream.Read(rev_fromArrayPool, 0, packageLen);
@ -419,7 +419,7 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
DataCallBackReady(token, rev_span);
//回收这里依赖DataCallBackReady中有一次数据拷贝这个后续还要进一步精进性能优化否则不能在这里回收否则影响业务层
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
} while (token.memoryStream.Length > 4);
}

View File

@ -25,9 +25,9 @@ namespace HaoYueNet.ClientNetwork
private static int MaxSendIndexNum = 3;
//响应倒计时计数
private static int RevIndex=0;
private static int RevIndex = 0;
//发送倒计时计数
private static int SendIndex=0;
private static int SendIndex = 0;
//计时器间隔
private static int TimerInterval = 3000;
@ -38,7 +38,7 @@ namespace HaoYueNet.ClientNetwork
public static int LastConnectPort;
public bool bDetailedLog = false;
public bool Init(string IP, int port,bool isHadDetailedLog = true, bool bBindReuseAddress = false,int bBindport = 0,AddressFamily addressFamily = AddressFamily.InterNetwork)
public bool Init(string IP, int port, bool isHadDetailedLog = true, bool bBindReuseAddress = false, int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
LogOut("==>初始化网络核心");
@ -63,7 +63,7 @@ namespace HaoYueNet.ClientNetwork
//带回调的
try
{
if(bDetailedLog)
if (bDetailedLog)
LogOut("连接到远程IP " + IP + ":" + port);
else
LogOut("连接到远程服务");
@ -111,13 +111,13 @@ namespace HaoYueNet.ClientNetwork
client.Close();
}
private void SendToSocket(byte[] data)
private void SendToSocket(byte[] data, int usefulLenght)
{
//已拼接包长度,这里不再需要拼接长度
//data = SendDataWithHead(data);
try
{
SendWithIndex(data);
SendWithIndex(data, usefulLenght);
}
catch (Exception ex)
{
@ -132,7 +132,7 @@ namespace HaoYueNet.ClientNetwork
{
try
{
SendWithIndex(HeartbeatData);
SendWithIndex(HeartbeatData, HeartbeatData.Length);
}
catch (Exception ex)
{
@ -148,14 +148,14 @@ namespace HaoYueNet.ClientNetwork
/// 发送数据并计数
/// </summary>
/// <param name="data"></param>
private void SendWithIndex(byte[] data)
private void SendWithIndex(byte[] data, int usefulLenght)
{
lock (sendLock)
{
//增加发送计数
SendIndex = MaxSendIndexNum;
//发送数据
client.Send(data);
client.Send(data, usefulLenght, SocketFlags.None);
}
}
@ -164,12 +164,33 @@ namespace HaoYueNet.ClientNetwork
/// </summary>
/// <param name="CMDID"></param>
/// <param name="data">序列化之后的数据</param>
public void SendToServer(int CMDID,byte[] data)
public virtual void SendToServer(int CmdID, byte[] data)
{
byte[] _finaldata = HunterNet_C2S.CreatePkgData((ushort)CMDID, data);
SendToSocket(_finaldata);
SendToServerWithLength(CmdID, ref data, data.Length);
//int allDataLength = HunterNet_C2S.GetAllLengthByBody(data);
//byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
//HunterNet_C2S.CreatePkgData((ushort)CmdID, data, ref _finaldata, out int usefulLenght);
//SendToSocket(_finaldata, usefulLenght);
//BytesArrayPool.ReturnBuffer(_finaldata);
//byte[] _finaldata = HunterNet_C2S.CreatePkgData((ushort)CmdID, data);
//SendToSocket(_finaldata);
}
/// <summary>
/// 供外部调用 发送消息
/// </summary>
/// <param name="CMDID"></param>
/// <param name="data">序列化之后的数据</param>
public virtual void SendToServerWithLength(int CmdID, ref byte[] data, int len)
{
int allDataLength = HunterNet_C2S.GetAllLengthByUsedLen(len);
byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
HunterNet_C2S.CreatePkgData((ushort)CmdID, data, len, ref _finaldata, out int usefulLenght);
SendToSocket(_finaldata, usefulLenght);
BytesArrayPool.ReturnBuffer(_finaldata);
}
#region
public delegate void OnReceiveDataHandler(int CMDID, int ERRCODE, byte[] data);
public delegate void OnConnectedHandler(bool IsConnected);
@ -247,7 +268,7 @@ namespace HaoYueNet.ClientNetwork
return;
}
}
catch(Exception ex)
catch (Exception ex)
{
//清理数据
reciveMemoryStream.SetLength(0);

View File

@ -18,22 +18,22 @@ namespace HaoYueNet.ClientNetwork
private static int MaxSendIndexNum = 3;
//响应倒计时计数
private static int RevIndex=0;
private static int RevIndex = 0;
//发送倒计时计数
private static int SendIndex=0;
private static int SendIndex = 0;
//计时器间隔
private static int TimerInterval = 3000;
private System.Timers.Timer _heartTimer;
public void Init(bool bBindReuseAddress = false,int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
public void Init(bool bBindReuseAddress = false, int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
LogOut("==>初始化网络核心");
RevIndex = MaxRevIndexNum;
SendIndex = MaxSendIndexNum;
client = new Socket(addressFamily,SocketType.Stream, ProtocolType.Tcp);
client = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
if (bBindReuseAddress)
{
client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@ -81,13 +81,13 @@ namespace HaoYueNet.ClientNetwork
client.Close();
}
private void SendToSocket(byte[] data)
private void SendToSocket(byte[] data, int usefulLenght)
{
//已拼接包长度,这里不再需要拼接长度
//data = SendDataWithHead(data);
try
{
SendWithIndex(data);
SendWithIndex(data, usefulLenght);
}
catch (Exception ex)
{
@ -102,7 +102,7 @@ namespace HaoYueNet.ClientNetwork
{
try
{
SendWithIndex(BaseData.HeartbeatData);
SendWithIndex(BaseData.HeartbeatData, BaseData.HeartbeatData.Length);
}
catch (Exception ex)
{
@ -117,12 +117,12 @@ namespace HaoYueNet.ClientNetwork
/// 发送数据并计数
/// </summary>
/// <param name="data"></param>
private void SendWithIndex(byte[] data)
private void SendWithIndex(byte[] data, int usefulLenght)
{
//增加发送计数
SendIndex = MaxSendIndexNum;
//发送数据
client.Send(data);
client.Send(data, usefulLenght, SocketFlags.None);
}
/// <summary>
@ -133,8 +133,15 @@ namespace HaoYueNet.ClientNetwork
/// <param name="data"></param>
public void SendToSocket(int CMDID, int ERRCODE, byte[] data)
{
byte[] _finaldata = HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data);
SendToSocket(_finaldata);
int allDataLength = HunterNet_C2S.GetAllLengthByBody(data);
byte[] _finaldata = BytesArrayPool.RentBuffer(allDataLength);
HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data, ref _finaldata, out int usefulLenght);
SendToSocket(_finaldata, usefulLenght);
BytesArrayPool.ReturnBuffer(_finaldata);
//byte[] _finaldata = HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data);
//SendToSocket(_finaldata);
}
public delegate void OnDataCallBack_Data(int CMDID, int ERRCODE, byte[] data);

View File

@ -205,7 +205,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
while (true)
{
//申请byte池 一定要记得回收!!
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(1024 * 1024 * 2);
byte[] rev_fromArrayPool = BytesArrayPool.RentBuffer(1024 * 1024 * 2);
int effective = 0;
try
@ -219,7 +219,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
//远程主机强迫关闭了一个现有的连接
OnCloseReady(client);
//回收
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
return;
}
}
@ -238,7 +238,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode
reciveMemoryStream.Write(rev_fromArrayPool, 0, effective);//将接受到的数据写入内存流中
//回收
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
BytesArrayPool.ReturnBuffer(rev_fromArrayPool);
DataCallBackReady(client, reciveMemoryStream.ToArray());
//流复用的方式 不用重新new申请