合理使用ArrayPool
This commit is contained in:
parent
c1a3650a95
commit
3036ef0e05
@ -1,4 +1,5 @@
|
|||||||
//using HunterProtobufCore;
|
//using HunterProtobufCore;
|
||||||
|
using System.Buffers;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@ -364,90 +365,67 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// check if the remote host closed the connection
|
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||||
{
|
{
|
||||||
//读取数据
|
|
||||||
//byte[] data = new byte[e.BytesTransferred];
|
|
||||||
//Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);
|
|
||||||
//lock (token.Buffer)
|
|
||||||
lock (token.memoryStream)
|
lock (token.memoryStream)
|
||||||
{
|
{
|
||||||
//token.Buffer.AddRange(data);
|
|
||||||
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//如果包头不完整
|
if (token.memoryStream.Length < 4) break;//包头不完整,继续接收
|
||||||
//if (token.Buffer.Count < 4)
|
|
||||||
if (token.memoryStream.Length < 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
////判断包的长度
|
|
||||||
//byte[] lenBytes = token.Buffer.GetRange(0, 4).ToArray();
|
|
||||||
//int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
|
||||||
//if (packageLen > token.Buffer.Count - 4)
|
|
||||||
//{ //长度不够时,退出循环,让程序继续接收
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
long FristBeginPos = token.memoryStream.Position;
|
long FristBeginPos = token.memoryStream.Position;
|
||||||
byte[] lenBytes = new byte[4];
|
|
||||||
|
//从Byte池申请
|
||||||
|
byte[] lenBytes = ArrayPool<byte>.Shared.Rent(4);
|
||||||
|
|
||||||
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
token.memoryStream.Read(lenBytes, 0, 4);
|
token.memoryStream.Read(lenBytes, 0, 4);
|
||||||
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
||||||
|
|
||||||
|
//归还byte[]
|
||||||
|
ArrayPool<byte>.Shared.Return(lenBytes);
|
||||||
|
|
||||||
if (packageLen > token.memoryStream.Length - 4)
|
if (packageLen > token.memoryStream.Length - 4)
|
||||||
{
|
{
|
||||||
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
||||||
//长度不够时,退出循环,让程序继续接收
|
break;//长度不够时,退出循环,让程序继续接收
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////包够长时,则提取出来,交给后面的程序去处理
|
//申请byte池 一定要记得回收!!
|
||||||
//byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray();
|
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(packageLen);
|
||||||
|
|
||||||
byte[] rev = new byte[packageLen];
|
|
||||||
token.memoryStream.Seek(4, SeekOrigin.Begin);
|
token.memoryStream.Seek(4, SeekOrigin.Begin);
|
||||||
token.memoryStream.Read(rev, 0, packageLen);
|
token.memoryStream.Read(rev_fromArrayPool, 0, packageLen);
|
||||||
|
|
||||||
//从数据池中移除这组数据
|
|
||||||
//lock (token.Buffer)
|
|
||||||
//{
|
|
||||||
// token.Buffer.RemoveRange(0, packageLen + 4);
|
|
||||||
//}
|
|
||||||
|
|
||||||
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
||||||
//从数据池中移除这组数据
|
//从数据池中移除这组数据
|
||||||
lock (token.memoryStream)
|
lock (token.memoryStream)
|
||||||
{
|
{
|
||||||
//token.memoryStream.Position = 0;
|
|
||||||
//token.memoryStream.SetLength(0);
|
|
||||||
int numberOfBytesToRemove = packageLen + 4;
|
int numberOfBytesToRemove = packageLen + 4;
|
||||||
byte[] buf = token.memoryStream.GetBuffer();
|
byte[] buf = token.memoryStream.GetBuffer();
|
||||||
Buffer.BlockCopy(buf, numberOfBytesToRemove, buf, 0, (int)token.memoryStream.Length - numberOfBytesToRemove);
|
Buffer.BlockCopy(buf, numberOfBytesToRemove, buf, 0, (int)token.memoryStream.Length - numberOfBytesToRemove);
|
||||||
token.memoryStream.SetLength(token.memoryStream.Length - numberOfBytesToRemove);
|
token.memoryStream.SetLength(token.memoryStream.Length - numberOfBytesToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataCallBackReady(token, rev);
|
//用Span内存切片,因为来自ArrayPool的byte长度,可能大于本身申请的长度
|
||||||
|
Span<byte> rev_span = rev_fromArrayPool;
|
||||||
|
rev_span = rev_span.Slice(0, packageLen);
|
||||||
|
DataCallBackReady(token, rev_span);
|
||||||
|
|
||||||
//这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收.
|
//回收(这里依赖DataCallBackReady中,有一次数据拷贝,这个后续还要进一步精进性能优化,否则不能在这里回收,否则影响业务层)
|
||||||
//若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了.
|
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
|
||||||
//} while (token.Buffer.Count > 4);
|
|
||||||
} while (token.memoryStream.Length > 4);
|
} while (token.memoryStream.Length > 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明
|
//如果返回为False则代表此刻已经完成,不必等待完成端口回调,则直接调用ProcessReceive
|
||||||
if (!token.Socket.ReceiveAsync(e))
|
if (!token.Socket.ReceiveAsync(e))
|
||||||
{
|
this.ProcessReceive(e);
|
||||||
ProcessReceive(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//尝试性,清理数据
|
//清理数据
|
||||||
token.memoryStream.SetLength(0);
|
token.memoryStream.SetLength(0);
|
||||||
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,7 +620,7 @@ namespace HaoYueNet.ClientNetwork.IOCPMode
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 处理前预备
|
#region 处理前预备
|
||||||
private void DataCallBackReady(AsyncUserToken sk, byte[] data)
|
private void DataCallBackReady(AsyncUserToken sk, Span<byte> data)
|
||||||
{
|
{
|
||||||
//增加接收计数
|
//增加接收计数
|
||||||
sk.RevIndex = MaxRevIndexNum;
|
sk.RevIndex = MaxRevIndexNum;
|
||||||
|
@ -257,8 +257,8 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
OnReceiveData(CmdID, Error, resultdata);
|
OnReceiveData(CmdID, Error, resultdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个反复使用的内存流
|
||||||
byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
byte[] reciveBuffer = new byte[1024 * 1024 * 2];//开辟一个反复使用的byte[]
|
||||||
private void Recive(object o)
|
private void Recive(object o)
|
||||||
{
|
{
|
||||||
var client = o as Socket;
|
var client = o as Socket;
|
||||||
@ -312,12 +312,6 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
//↓↓↓↓↓↓↓↓ ↓↓↓
|
//↓↓↓↓↓↓↓↓ ↓↓↓
|
||||||
if (getData.Length - StartIndex < HeadLength || HeadLength == -1)
|
if (getData.Length - StartIndex < HeadLength || HeadLength == -1)
|
||||||
{
|
{
|
||||||
/* 一种清空流的方式
|
|
||||||
memoryStream.Close();//关闭内存流
|
|
||||||
memoryStream.Dispose();//释放内存资源
|
|
||||||
memoryStream = new MemoryStream();//创建新的内存流
|
|
||||||
*/
|
|
||||||
|
|
||||||
//流复用的方式 不用重新new申请
|
//流复用的方式 不用重新new申请
|
||||||
reciveMemoryStream.Position = 0;
|
reciveMemoryStream.Position = 0;
|
||||||
reciveMemoryStream.SetLength(0);
|
reciveMemoryStream.SetLength(0);
|
||||||
@ -327,16 +321,7 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//把头去掉,就可以吃了,蛋白质是牛肉的六倍
|
|
||||||
//DataCallBackReady(getData.Skip(StartIndex+4).Take(HeadLength-4).ToArray());
|
|
||||||
|
|
||||||
int CoreLenght = HeadLength - 4;
|
int CoreLenght = HeadLength - 4;
|
||||||
|
|
||||||
//改为Array.Copy 提升效率
|
|
||||||
//byte[] retData = new byte[CoreLenght];
|
|
||||||
//Array.Copy(getData, StartIndex + 4, retData, 0, CoreLenght);
|
|
||||||
//DataCallBackReady(retData);
|
|
||||||
|
|
||||||
//用Span
|
//用Span
|
||||||
Span<byte> getData_span = getData;
|
Span<byte> getData_span = getData;
|
||||||
getData_span = getData_span.Slice(StartIndex + 4, CoreLenght);
|
getData_span = getData_span.Slice(StartIndex + 4, CoreLenght);
|
||||||
|
@ -182,24 +182,6 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event delegate_str OnLogOut;
|
public event delegate_str OnLogOut;
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 用于调用者回调的虚函数
|
|
||||||
///// </summary>
|
|
||||||
///// <param name="data"></param>
|
|
||||||
//public virtual void DataCallBack(int CMDID,int ERRCODE,byte[] data)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 断开连接
|
|
||||||
///// </summary>
|
|
||||||
///// <param name="sk"></param>
|
|
||||||
//public virtual void OnClose()
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 做好处理的连接管理
|
/// 做好处理的连接管理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -236,16 +218,12 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
HunterNet_S2C _c2s = DeSerizlize<HunterNet_S2C>(data);
|
|
||||||
OnDataCallBack(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray());
|
|
||||||
*/
|
|
||||||
HunterNet_S2C.AnalysisPkgData(data, out ushort CmdID, out ushort Error, out byte[] resultdata);
|
HunterNet_S2C.AnalysisPkgData(data, out ushort CmdID, out ushort Error, out byte[] resultdata);
|
||||||
OnDataCallBack(CmdID, Error, resultdata);
|
OnDataCallBack(CmdID, Error, resultdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个反复使用的内存流
|
||||||
byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
byte[] reciveBuffer = new byte[1024 * 1024 * 2];//开辟一个反复使用的byte[]
|
||||||
private void Recive(object o)
|
private void Recive(object o)
|
||||||
{
|
{
|
||||||
var client = o as Socket;
|
var client = o as Socket;
|
||||||
@ -299,12 +277,6 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
//↓↓↓↓↓↓↓↓ ↓↓↓
|
//↓↓↓↓↓↓↓↓ ↓↓↓
|
||||||
if (getData.Length - StartIndex < HeadLength || HeadLength == -1)
|
if (getData.Length - StartIndex < HeadLength || HeadLength == -1)
|
||||||
{
|
{
|
||||||
/* 一种清空流的方式
|
|
||||||
memoryStream.Close();//关闭内存流
|
|
||||||
memoryStream.Dispose();//释放内存资源
|
|
||||||
memoryStream = new MemoryStream();//创建新的内存流
|
|
||||||
*/
|
|
||||||
|
|
||||||
//流复用的方式 不用重新new申请
|
//流复用的方式 不用重新new申请
|
||||||
reciveMemoryStream.Position = 0;
|
reciveMemoryStream.Position = 0;
|
||||||
reciveMemoryStream.SetLength(0);
|
reciveMemoryStream.SetLength(0);
|
||||||
@ -314,16 +286,8 @@ namespace HaoYueNet.ClientNetwork
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//把头去掉,就可以吃了,蛋白质是牛肉的六倍
|
|
||||||
//DataCallBackReady(getData.Skip(StartIndex+4).Take(HeadLength-4).ToArray());
|
|
||||||
|
|
||||||
int CoreLenght = HeadLength - 4;
|
int CoreLenght = HeadLength - 4;
|
||||||
|
|
||||||
//改为Array.Copy 提升效率
|
|
||||||
//byte[] retData = new byte[CoreLenght];
|
|
||||||
//Array.Copy(getData, StartIndex + 4, retData, 0, CoreLenght);
|
|
||||||
//DataCallBackReady(retData);
|
|
||||||
|
|
||||||
//用Span
|
//用Span
|
||||||
Span<byte> getData_span = getData;
|
Span<byte> getData_span = getData;
|
||||||
getData_span = getData_span.Slice(StartIndex + 4, CoreLenght);
|
getData_span = getData_span.Slice(StartIndex + 4, CoreLenght);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using System.Buffers;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using static HaoYueNet.ClientNetwork.BaseData;
|
using static HaoYueNet.ClientNetwork.BaseData;
|
||||||
|
|
||||||
@ -190,17 +191,20 @@ namespace HaoYueNet.ClientNetwork.OtherMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
||||||
byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
//byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
||||||
private void Recive(object o)
|
private void Recive(object o)
|
||||||
{
|
{
|
||||||
var client = o as Socket;
|
var client = o as Socket;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
//申请byte池 一定要记得回收!!
|
||||||
|
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(1024 * 1024 * 2);
|
||||||
|
|
||||||
int effective = 0;
|
int effective = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
effective = client.Receive(reciveBuffer);
|
effective = client.Receive(rev_fromArrayPool);
|
||||||
if (effective == 0)//为0表示已经断开连接,放到后面处理
|
if (effective == 0)//为0表示已经断开连接,放到后面处理
|
||||||
{
|
{
|
||||||
//清理数据
|
//清理数据
|
||||||
@ -208,6 +212,8 @@ namespace HaoYueNet.ClientNetwork.OtherMode
|
|||||||
reciveMemoryStream.Seek(0, SeekOrigin.Begin);
|
reciveMemoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
//远程主机强迫关闭了一个现有的连接
|
//远程主机强迫关闭了一个现有的连接
|
||||||
OnCloseReady(client);
|
OnCloseReady(client);
|
||||||
|
//回收
|
||||||
|
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +229,11 @@ namespace HaoYueNet.ClientNetwork.OtherMode
|
|||||||
//断开连接
|
//断开连接
|
||||||
}
|
}
|
||||||
|
|
||||||
reciveMemoryStream.Write(reciveBuffer, 0, effective);//将接受到的数据写入内存流中
|
reciveMemoryStream.Write(rev_fromArrayPool, 0, effective);//将接受到的数据写入内存流中
|
||||||
|
|
||||||
|
//回收
|
||||||
|
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
|
||||||
|
|
||||||
DataCallBackReady(client, reciveMemoryStream.ToArray());
|
DataCallBackReady(client, reciveMemoryStream.ToArray());
|
||||||
//流复用的方式 不用重新new申请
|
//流复用的方式 不用重新new申请
|
||||||
reciveMemoryStream.Position = 0;
|
reciveMemoryStream.Position = 0;
|
||||||
|
@ -192,8 +192,8 @@ namespace HaoYueNet.ClientNetwork.OtherMode
|
|||||||
OnReceiveData(data);
|
OnReceiveData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个反复使用的内存流
|
||||||
byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
byte[] reciveBuffer = new byte[1024 * 1024 * 2];//开辟一个反复使用的byte[]
|
||||||
private void Recive(object o)
|
private void Recive(object o)
|
||||||
{
|
{
|
||||||
var client = o as Socket;
|
var client = o as Socket;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace HaoYueNet.ServerNetwork
|
namespace HaoYueNet.ServerNetwork
|
||||||
{
|
{
|
||||||
@ -142,7 +143,7 @@ namespace HaoYueNet.ServerNetwork
|
|||||||
return BufferData;
|
return BufferData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AnalysisPkgData(Span<byte> srcdata, out UInt16 CmdID, out byte[] data)
|
public static void AnalysisPkgData(Span<byte> srcdata,out UInt16 CmdID, out byte[] data)
|
||||||
{
|
{
|
||||||
//data = new byte[srcdata.Length - 2];
|
//data = new byte[srcdata.Length - 2];
|
||||||
//CmdID = BitConverter.ToUInt16(srcdata, 0);
|
//CmdID = BitConverter.ToUInt16(srcdata, 0);
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace HaoYueNet.ServerNetwork.NetWork
|
|
||||||
{
|
|
||||||
public static class ArrayPoolManager
|
|
||||||
{
|
|
||||||
static ArrayPool<byte> instance = ArrayPool<byte>.Shared;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 租用指定大小byte数组
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lenght"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static byte[] RentByteArr(int lenght)
|
|
||||||
{
|
|
||||||
return instance.Rent(lenght);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 将数组归还给池
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lenght"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static void ReturnByteArr(byte[] byteArr)
|
|
||||||
{
|
|
||||||
instance.Return(byteArr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -373,51 +373,32 @@ namespace HaoYueNet.ServerNetwork
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// check if the remote host closed the connection
|
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||||
{
|
{
|
||||||
//读取数据
|
//读取数据
|
||||||
//byte[] data = new byte[e.BytesTransferred];
|
|
||||||
//Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);
|
|
||||||
//lock (token.Buffer)
|
|
||||||
lock(token.memoryStream)
|
lock(token.memoryStream)
|
||||||
{
|
{
|
||||||
//token.Buffer.AddRange(data);
|
|
||||||
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
||||||
//DataCallBackReady(token, data);
|
|
||||||
////从数据池中移除这组数据
|
|
||||||
//lock (token.Buffer)
|
|
||||||
//{
|
|
||||||
// token.Buffer.Clear();
|
|
||||||
//}
|
|
||||||
|
|
||||||
DataCallBackReady(token, token.memoryStream.ToArray());
|
DataCallBackReady(token, token.memoryStream.ToArray());
|
||||||
//流复用的方式 不用重新new申请
|
//流复用的方式 不用重新new申请
|
||||||
token.memoryStream.Position = 0;
|
token.memoryStream.Position = 0;
|
||||||
token.memoryStream.SetLength(0);
|
token.memoryStream.SetLength(0);
|
||||||
|
|
||||||
//这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收.
|
|
||||||
//若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了.
|
|
||||||
} while (token.memoryStream.Length > 0);
|
} while (token.memoryStream.Length > 0);
|
||||||
//} while (token.Buffer.Count > 4);
|
//} while (token.Buffer.Count > 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明
|
|
||||||
if (!token.Socket.ReceiveAsync(e))
|
if (!token.Socket.ReceiveAsync(e))
|
||||||
{
|
|
||||||
this.ProcessReceive(e);
|
this.ProcessReceive(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//清理数据
|
//清理数据
|
||||||
token.memoryStream.SetLength(0);
|
token.memoryStream.SetLength(0);
|
||||||
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//using HunterProtobufCore;
|
//using HunterProtobufCore;
|
||||||
using HaoYueNet.ServerNetwork.NetWork;
|
using System.Buffers;
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using static HaoYueNet.ServerNetwork.BaseData;
|
using static HaoYueNet.ServerNetwork.BaseData;
|
||||||
@ -375,96 +374,67 @@ namespace HaoYueNet.ServerNetwork
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// check if the remote host closed the connection
|
|
||||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||||
{
|
{
|
||||||
//读取数据
|
|
||||||
//byte[] data = new byte[e.BytesTransferred];
|
|
||||||
//Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);
|
|
||||||
//lock (token.Buffer)
|
|
||||||
lock(token.memoryStream)
|
lock(token.memoryStream)
|
||||||
{
|
{
|
||||||
//token.Buffer.AddRange(data);
|
|
||||||
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//如果包头不完整
|
if (token.memoryStream.Length < 4) break;//包头不完整,继续接收
|
||||||
//if (token.Buffer.Count < 4)
|
|
||||||
if (token.memoryStream.Length < 4)
|
|
||||||
break;
|
|
||||||
|
|
||||||
////判断包的长度
|
|
||||||
//byte[] lenBytes = token.Buffer.GetRange(0, 4).ToArray();
|
|
||||||
//int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
|
||||||
//if (packageLen > token.Buffer.Count - 4)
|
|
||||||
//{ //长度不够时,退出循环,让程序继续接收
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
long FristBeginPos = token.memoryStream.Position;
|
long FristBeginPos = token.memoryStream.Position;
|
||||||
//byte[] lenBytes = new byte[4];
|
|
||||||
byte[] lenBytes = ArrayPoolManager.RentByteArr(4);
|
//从Byte池申请
|
||||||
|
byte[] lenBytes = ArrayPool<byte>.Shared.Rent(4);
|
||||||
|
|
||||||
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
token.memoryStream.Read(lenBytes, 0, 4);
|
token.memoryStream.Read(lenBytes, 0, 4);
|
||||||
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4;
|
||||||
ArrayPoolManager.ReturnByteArr(lenBytes);
|
|
||||||
|
|
||||||
|
//归还byte[]
|
||||||
|
ArrayPool<byte>.Shared.Return(lenBytes);
|
||||||
|
|
||||||
if (packageLen > token.memoryStream.Length - 4)
|
if (packageLen > token.memoryStream.Length - 4)
|
||||||
{
|
{
|
||||||
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
||||||
//长度不够时,退出循环,让程序继续接收
|
break;//长度不够时,退出循环,让程序继续接收
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////包够长时,则提取出来,交给后面的程序去处理
|
//申请byte池 一定要记得回收!!
|
||||||
//byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray();
|
byte[] rev_fromArrayPool = ArrayPool<byte>.Shared.Rent(packageLen);
|
||||||
|
|
||||||
byte[] rev = new byte[packageLen];
|
|
||||||
|
|
||||||
token.memoryStream.Seek(4, SeekOrigin.Begin);
|
token.memoryStream.Seek(4, SeekOrigin.Begin);
|
||||||
token.memoryStream.Read(rev, 0, packageLen);
|
token.memoryStream.Read(rev_fromArrayPool, 0, packageLen);
|
||||||
|
|
||||||
//从数据池中移除这组数据
|
|
||||||
//lock (token.Buffer)
|
|
||||||
//{
|
|
||||||
// token.Buffer.RemoveRange(0, packageLen + 4);
|
|
||||||
//}
|
|
||||||
|
|
||||||
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin);
|
||||||
//从数据池中移除这组数据
|
//从数据池中移除这组数据
|
||||||
lock (token.memoryStream)
|
lock (token.memoryStream)
|
||||||
{
|
{
|
||||||
//token.memoryStream.Position = 0;
|
|
||||||
//token.memoryStream.SetLength(0);
|
|
||||||
int numberOfBytesToRemove = packageLen + 4;
|
int numberOfBytesToRemove = packageLen + 4;
|
||||||
byte[] buf = token.memoryStream.GetBuffer();
|
byte[] buf = token.memoryStream.GetBuffer();
|
||||||
Buffer.BlockCopy(buf, numberOfBytesToRemove, buf, 0, (int)token.memoryStream.Length - numberOfBytesToRemove);
|
Buffer.BlockCopy(buf, numberOfBytesToRemove, buf, 0, (int)token.memoryStream.Length - numberOfBytesToRemove);
|
||||||
token.memoryStream.SetLength(token.memoryStream.Length - numberOfBytesToRemove);
|
token.memoryStream.SetLength(token.memoryStream.Length - numberOfBytesToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataCallBackReady(token, rev);
|
//用Span内存切片,因为来自ArrayPool的byte长度,可能大于本身申请的长度
|
||||||
|
Span<byte> rev_span = rev_fromArrayPool;
|
||||||
|
rev_span = rev_span.Slice(0, packageLen);
|
||||||
|
DataCallBackReady(token, rev_span);
|
||||||
|
|
||||||
//这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收.
|
//回收(这里依赖DataCallBackReady中,有一次数据拷贝,这个后续还要进一步精进性能优化,否则不能在这里回收,否则影响业务层)
|
||||||
//若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了.
|
ArrayPool<byte>.Shared.Return(rev_fromArrayPool);
|
||||||
//} while (token.Buffer.Count > 4);
|
|
||||||
} while (token.memoryStream.Length > 4);
|
} while (token.memoryStream.Length > 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明
|
//如果返回为False则代表此刻已经完成,不必等待完成端口回调,则直接调用ProcessReceive
|
||||||
if (!token.Socket.ReceiveAsync(e))
|
if (!token.Socket.ReceiveAsync(e))
|
||||||
{
|
|
||||||
this.ProcessReceive(e);
|
this.ProcessReceive(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//尝试性,清理数据
|
//清理数据
|
||||||
token.memoryStream.SetLength(0);
|
token.memoryStream.SetLength(0);
|
||||||
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
token.memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
CloseClientSocket(e);
|
CloseClientSocket(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,8 +459,6 @@ namespace HaoYueNet.ServerNetwork
|
|||||||
}
|
}
|
||||||
void IO_Completed(object sender, SocketAsyncEventArgs e)
|
void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||||
{
|
{
|
||||||
// determine which type of operation just completed and call the associated handler
|
|
||||||
|
|
||||||
switch (e.LastOperation)
|
switch (e.LastOperation)
|
||||||
{
|
{
|
||||||
case SocketAsyncOperation.Receive:
|
case SocketAsyncOperation.Receive:
|
||||||
@ -661,7 +629,7 @@ namespace HaoYueNet.ServerNetwork
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 处理前预备
|
#region 处理前预备
|
||||||
private void DataCallBackReady(AsyncUserToken sk, byte[] data)
|
private void DataCallBackReady(AsyncUserToken sk, Span<byte> data)
|
||||||
{
|
{
|
||||||
//增加接收计数
|
//增加接收计数
|
||||||
sk.RevIndex = MaxRevIndexNum;
|
sk.RevIndex = MaxRevIndexNum;
|
||||||
|
@ -260,8 +260,9 @@ namespace HaoYueNet.ClientNetwork.Standard2
|
|||||||
OnReceiveData(CmdID, Error, resultdata);
|
OnReceiveData(CmdID, Error, resultdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流
|
|
||||||
byte[] reciveBuffer = new byte[1024 * 1024 * 2];
|
MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个反复使用的内存流
|
||||||
|
byte[] reciveBuffer = new byte[1024 * 1024 * 2];//开辟一个反复使用的byte[]
|
||||||
private void Recive(object o)
|
private void Recive(object o)
|
||||||
{
|
{
|
||||||
var client = o as Socket;
|
var client = o as Socket;
|
||||||
|
Loading…
Reference in New Issue
Block a user