From 8fd9761eb28ec8ef68714f0d9ef04dd55be1d0c7 Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Fri, 18 Oct 2024 16:55:40 +0800 Subject: [PATCH] standard2 --- .../NetworkHelperCore.cs | 4 +- .../NetworkHelperP2PCore.cs | 6 +- .../NetworkHelperCore_ListenerMode.cs | 16 +- .../OtherMode/NetworkHelperCore_SourceMode.cs | 4 +- .../BaseData.cs | 72 +- .../IOCPMode/AsyncUserToken.cs | 56 ++ .../IOCPMode/BufferManager.cs | 61 ++ .../IOCPMode/MemoryStreamPool.cs | 43 ++ .../IOCPMode/SocketEventPool.cs | 47 ++ .../IOCPMode/TcpSaeaClient.cs | 710 ++++++++++++++++++ .../IOCPMode/TokenMsgPool.cs | 130 ++++ .../NetworkHelperCore.cs | 73 +- .../NetworkHelperP2PCore.cs | 93 +-- 13 files changed, 1102 insertions(+), 213 deletions(-) create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/AsyncUserToken.cs create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/BufferManager.cs create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/MemoryStreamPool.cs create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/SocketEventPool.cs create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TcpSaeaClient.cs create mode 100644 NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TokenMsgPool.cs diff --git a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs index 18f947d..1461a88 100644 --- a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs +++ b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs @@ -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) + public bool Init(string IP, int port,bool isHadDetailedLog = true, bool bBindReuseAddress = false,int bBindport = 0,AddressFamily addressFamily = AddressFamily.InterNetwork) { LogOut("==>初始化网络核心"); @@ -43,7 +43,7 @@ namespace HaoYueNet.ClientNetwork RevIndex = MaxRevIndexNum; SendIndex = MaxSendIndexNum; - client = new Socket(SocketType.Stream, ProtocolType.Tcp); + client = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); if (bBindReuseAddress) { client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); diff --git a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperP2PCore.cs b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperP2PCore.cs index f8cbfb2..de60879 100644 --- a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperP2PCore.cs +++ b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperP2PCore.cs @@ -24,15 +24,13 @@ namespace HaoYueNet.ClientNetwork private System.Timers.Timer _heartTimer; - public void Init(bool bBindReuseAddress = false,int bBindport = 0) + public void Init(bool bBindReuseAddress = false,int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork) { - LogOut("==>初始化网络核心"); - RevIndex = MaxRevIndexNum; SendIndex = MaxSendIndexNum; - client = new Socket(SocketType.Stream, ProtocolType.Tcp); + client = new Socket(addressFamily,SocketType.Stream, ProtocolType.Tcp); if (bBindReuseAddress) { client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); diff --git a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs index 6f37465..75c86bc 100644 --- a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs +++ b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs @@ -8,7 +8,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode public class NetworkHelperCore_ListenerMode { private Socket serversocket; - private Dictionary mDictHandleClient; + private Dictionary mDictHandleClient; //响应倒计时计数最大值 private static int MaxRevIndexNum = 50; @@ -27,12 +27,12 @@ namespace HaoYueNet.ClientNetwork.OtherMode public static int LastConnectPort; public bool bDetailedLog = false; - public void Init(int port) + public void Init(int port, AddressFamily addressFamily = AddressFamily.InterNetwork) { mDictHandleClient = new Dictionary(); LogOut("==>初始化NetworkHelperCore_ListenerMode"); - serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + serversocket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port); serversocket.Bind(endPoint); // 绑定 serversocket.Listen(1); @@ -98,7 +98,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode ~NetworkHelperCore_ListenerMode() { nint[] keys = mDictHandleClient.Keys.ToArray(); - for (uint i = 0; i < keys.Length; i++) + for (uint i = 0; i < keys.Length; i++) { mDictHandleClient[keys[i]].Close(); } @@ -111,7 +111,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode //data = SendDataWithHead(data); try { - SendWithIndex(socket,data); + SendWithIndex(socket, data); } catch (Exception ex) { @@ -126,7 +126,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode /// 发送数据并计数 /// /// - private void SendWithIndex(Socket socket,byte[] data) + private void SendWithIndex(Socket socket, byte[] data) { //增加发送计数 SendIndex = MaxSendIndexNum; @@ -183,11 +183,11 @@ namespace HaoYueNet.ClientNetwork.OtherMode OnCloseReady(socket); } - private void DataCallBackReady(Socket socket,byte[] data) + private void DataCallBackReady(Socket socket, byte[] data) { //增加接收计数 RevIndex = MaxRevIndexNum; - OnReceive(socket,data); + OnReceive(socket, data); } MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个内存流 diff --git a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_SourceMode.cs b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_SourceMode.cs index 754f1a5..0af6c28 100644 --- a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_SourceMode.cs +++ b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_SourceMode.cs @@ -32,7 +32,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode public static int LastConnectPort; public bool bDetailedLog = false; - public bool Init(string IP, int port, bool isHadDetailedLog = true, bool bBindReuseAddress = false, int bBindport = 0) + public bool Init(string IP, int port, bool isHadDetailedLog = true, bool bBindReuseAddress = false, int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork) { LogOut("==>初始化网络核心"); @@ -40,7 +40,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode RevIndex = MaxRevIndexNum; SendIndex = MaxSendIndexNum; - client = new Socket(SocketType.Stream, ProtocolType.Tcp); + client = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); if (bBindReuseAddress) { client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/BaseData.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/BaseData.cs index 2daaeb4..6cddadf 100644 --- a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/BaseData.cs +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/BaseData.cs @@ -1,7 +1,6 @@ using System; using System.Net.Sockets; - -namespace HaoYueNet.ClientNetwork.Standard2 +namespace HaoYueNet.ClientNetwork { public static class BaseData { @@ -9,22 +8,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 /// 心跳包数据 /// public static byte[] HeartbeatData = new byte[5] { 0x05, 0x00, 0x00, 0x00, 0x00 }; - - public static void writeInt(byte[] buf, int offset, int value) - { - buf[offset++] = (byte)(255 & value); - buf[offset++] = (byte)(255 & value >> 8); - buf[offset++] = (byte)(255 & value >> 16); - //buf[offset++] = (byte)(255 & value >>> 24); - buf[offset++] = (byte)(255 & value >> 24); - } - - public static void writeUInt16(byte[] buf, int offset, int value) - { - buf[offset++] = (byte)(255 & value); - buf[offset++] = (byte)(255 & value >> 8); - } - public static class HunterNet_Heartbeat { public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs) @@ -32,47 +15,35 @@ namespace HaoYueNet.ClientNetwork.Standard2 myreadEventArgs.SetBuffer(HeartbeatData, 0, HeartbeatData.Length); } } - public static class HunterNet_S2C { 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); + byte[] data = CreatePkgData(CmdID, Error, AddonBytes_Data); + myreadEventArgs.SetBuffer(data,0,data.Length); } - public static byte[] CreatePkgData(UInt16 CmdID, UInt16 Error, byte[] AddonBytes_Data) { - //用Buffer.BlockCopy拷贝 //包长度 int AllLenght = 4 + 2 + 2 + AddonBytes_Data.Length; byte[] BufferData = new byte[AllLenght]; - //包长度 - writeInt(BufferData, 0, AllLenght); - + Buffer.BlockCopy(BitConverter.GetBytes(AllLenght), 0, BufferData, 0, sizeof(int)); //CMDID - writeUInt16(BufferData, 4, CmdID); - - //Error - writeUInt16(BufferData, 4 + 2, Error); - + Buffer.BlockCopy(BitConverter.GetBytes(CmdID), 0, BufferData, 4, sizeof(UInt16)); + //ErrID + 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; } - - public static void AnalysisPkgData(byte[] srcdata, out UInt16 CmdID, out UInt16 Error, out byte[] data) + public static void AnalysisPkgData(Span srcdata, out UInt16 CmdID, out UInt16 Error, out byte[] data) { - CmdID = BitConverter.ToUInt16(srcdata, 0); - Error = BitConverter.ToUInt16(srcdata, 2); - data = new byte[srcdata.Length - 2 - 2]; - Array.Copy(srcdata, 4, data, 0, data.Length); - + CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2).ToArray(), 0); + Error = BitConverter.ToUInt16(srcdata.Slice(2, 2).ToArray(), 0); + data = srcdata.Slice(2 + 2).ToArray(); } } - public static class HunterNet_C2S { public static void SetDataToSocketAsyncEventArgs(SocketAsyncEventArgs myreadEventArgs, UInt16 CmdID, byte[] AddonBytes_Data) @@ -80,35 +51,26 @@ namespace HaoYueNet.ClientNetwork.Standard2 byte[] data = CreatePkgData(CmdID, AddonBytes_Data); myreadEventArgs.SetBuffer(data, 0, data.Length); } - public static byte[] CreatePkgData(UInt16 CmdID, byte[] AddonBytes_Data) { byte[] AddonBytes_CmdID = BitConverter.GetBytes(CmdID); int AllLenght = AddonBytes_CmdID.Length + AddonBytes_Data.Length + 4; - int LastIndex = 0; //包长度 byte[] AddonBytes_Lenght = BitConverter.GetBytes(AllLenght); - byte[] BufferData = new byte[AllLenght]; //包长度 - Buffer.BlockCopy(AddonBytes_Lenght, 0, BufferData, LastIndex, AddonBytes_Lenght.Length); - LastIndex += AddonBytes_Lenght.Length; - + Buffer.BlockCopy(AddonBytes_Lenght, 0, BufferData, 0, AddonBytes_Lenght.Length); //CMDID - Buffer.BlockCopy(AddonBytes_CmdID, 0, BufferData, LastIndex, AddonBytes_CmdID.Length); - LastIndex += AddonBytes_CmdID.Length; - + Buffer.BlockCopy(AddonBytes_CmdID, 0, BufferData, 4, AddonBytes_CmdID.Length); //DATA - Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, LastIndex, AddonBytes_Data.Length); - LastIndex += AddonBytes_Data.Length; + Buffer.BlockCopy(AddonBytes_Data, 0, BufferData, 4 + 2, AddonBytes_Data.Length); return BufferData; } - public static void AnalysisPkgData(byte[] srcdata, out UInt16 CmdID, out byte[] data) + public static void AnalysisPkgData(Span srcdata, out UInt16 CmdID, out byte[] data) { - data = new byte[srcdata.Length - 2]; - CmdID = BitConverter.ToUInt16(srcdata, 0); - Array.Copy(srcdata, 2, data, 0, data.Length); + CmdID = BitConverter.ToUInt16(srcdata.Slice(0, 2).ToArray(),0); + data = srcdata.Slice(2).ToArray(); } } } diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/AsyncUserToken.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/AsyncUserToken.cs new file mode 100644 index 0000000..536135a --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/AsyncUserToken.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + public class AsyncUserToken + { + /// + /// 客户端IP地址 + /// + public IPAddress IPAddress { get; set; } + + /// + /// 远程地址 + /// + public EndPoint Remote { get; set; } + + /// + /// 通信SOKET + /// + public Socket Socket { get; set; } + + /// + /// 连接时间 + /// + public DateTime ConnectTime { get; set; } + + /// + /// 所属用户信息 + /// + public object UserInfo { get; set; } + + /// + /// 数据缓存区 + /// + //public List Buffer { get; set; } + + public MemoryStream memoryStream { get; set; } + + public AsyncUserToken() + { + //this.Buffer = new List(); + memoryStream = new MemoryStream(); + } + /// + /// 响应倒计时计数 + /// + public int RevIndex { get; set; } = 0; + /// + /// 发送倒计时计数 + /// + public int SendIndex { get; set; } = 0; + } +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/BufferManager.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/BufferManager.cs new file mode 100644 index 0000000..f3009ed --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/BufferManager.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Net.Sockets; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + public class BufferManager + { + int m_numBytes; // the total number of bytes controlled by the buffer pool + byte[] m_buffer; // the underlying byte array maintained by the Buffer Manager + Stack m_freeIndexPool; // + int m_currentIndex; + int m_bufferSize; + + public BufferManager(int totalBytes, int bufferSize) + { + m_numBytes = totalBytes; + m_currentIndex = 0; + m_bufferSize = bufferSize; + m_freeIndexPool = new Stack(); + } + + // Allocates buffer space used by the buffer pool + public void InitBuffer() + { + // create one big large buffer and divide that + // out to each SocketAsyncEventArg object + m_buffer = new byte[m_numBytes]; + } + + // Assigns a buffer from the buffer pool to the + // specified SocketAsyncEventArgs object + // + // true if the buffer was successfully set, else false + public bool SetBuffer(SocketAsyncEventArgs args) + { + + if (m_freeIndexPool.Count > 0) + { + args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize); + } + else + { + if (m_numBytes - m_bufferSize < m_currentIndex) + { + return false; + } + args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize); + m_currentIndex += m_bufferSize; + } + return true; + } + + // Removes the buffer from a SocketAsyncEventArg object. + // This frees the buffer back to the buffer pool + public void FreeBuffer(SocketAsyncEventArgs args) + { + m_freeIndexPool.Push(args.Offset); + args.SetBuffer(null, 0, 0); + } + } +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/MemoryStreamPool.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/MemoryStreamPool.cs new file mode 100644 index 0000000..81997c4 --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/MemoryStreamPool.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + + public class MemoryStreamPools + { + Stack m_pool; + + public MemoryStreamPools(int capacity) + { + m_pool = new Stack(capacity); + } + + public void Push(MemoryStream item) + { + if (item == null) { throw new ArgumentNullException("Items added to a MemoryStream cannot be null"); } + lock (m_pool) + { + m_pool.Push(item); + } + } + public MemoryStream Pop() + { + lock (m_pool) + { + return m_pool.Pop(); + } + } + + public int Count + { + get { return m_pool.Count; } + } + + public void Clear() + { + m_pool.Clear(); + } + } +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/SocketEventPool.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/SocketEventPool.cs new file mode 100644 index 0000000..0ddba78 --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/SocketEventPool.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + + public class SocketEventPool + { + Stack m_pool; + + public SocketEventPool(int capacity) + { + m_pool = new Stack(capacity); + } + + public void Push(SocketAsyncEventArgs item) + { + if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); } + lock (m_pool) + { + m_pool.Push(item); + } + } + + // Removes a SocketAsyncEventArgs instance from the pool + // and returns the object removed from the pool + public SocketAsyncEventArgs Pop() + { + lock (m_pool) + { + return m_pool.Pop(); + } + } + + // The number of SocketAsyncEventArgs instances in the pool + public int Count + { + get { return m_pool.Count; } + } + + public void Clear() + { + m_pool.Clear(); + } + } +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TcpSaeaClient.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TcpSaeaClient.cs new file mode 100644 index 0000000..e76d39b --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TcpSaeaClient.cs @@ -0,0 +1,710 @@ +//using HunterProtobufCore; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using static HaoYueNet.ClientNetwork.BaseData; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + public class TcpSaeaClient + { + #region 定义属性 + protected int MaxRevIndexNum = 50;//响应倒计时计数最大值 + protected int MaxSendIndexNum = 3;//发送倒计时计数最大值 + protected static int TimerInterval = 3000;//计时器间隔 + protected System.Timers.Timer _heartTimer;//心跳包计数器 + public int m_maxConnectNum; //最大连接数 + public int m_revBufferSize; //最大接收字节数 + protected BufferManager m_bufferManager; + protected const int opsToAlloc = 2; + protected SocketEventPool m_Receivepool; + protected SocketEventPool m_Sendpool; + protected TokenMsgPool msg_pool; + protected int m_clientCount; //连接的客户端数量 + protected Semaphore m_maxNumberAcceptedClients;//信号量 + protected Dictionary _DictSocketAsyncUserToken = new Dictionary(); + List m_clients; //客户端列表 + public List ClientList { private set { m_clients = value; } get { return m_clients; } } //获取客户端列表 + #endregion + + #region 定义委托 + /// + /// 客户端连接数量变化时触发 + /// + /// 当前增加客户的个数(用户退出时为负数,增加时为正数,一般为1) + /// 增加用户的信息 + public delegate void OnClientNumberChangeHandler(int num, AsyncUserToken token); + /// + /// 接收到客户端的数据 + /// + /// 客户端 + /// 客户端数据 + public delegate void OnReceiveDataHandler(AsyncUserToken sk, int CMDID, int ErrID, byte[] data); + /// + /// 断开连接 + /// + /// + public delegate void OnDisconnectHandler(AsyncUserToken sk); + /// + /// 日志 + /// + /// + public delegate void OnNetLogHandler(string msg); + #endregion + + #region 定义事件 + /// + /// 客户端连接数量变化事件 + /// + public event OnClientNumberChangeHandler OnClientNumberChange; + /// + /// 接收到客户端的数据事件 + /// + public event OnReceiveDataHandler OnReceive; + /// + /// 接收到客户端的断开连接 + /// + public event OnDisconnectHandler OnDisconnected; + /// + /// 网络库内部输出 + /// + public event OnNetLogHandler OnNetLog; + #endregion + + /// + /// 构造函数 + /// + /// 最大连接数 + /// 缓存区大小 + public TcpSaeaClient(int numConnections, int receiveBufferSize) + { + m_clientCount = 0; + m_maxConnectNum = numConnections; + m_revBufferSize = receiveBufferSize; + // allocate buffers such that the maximum number of sockets can have one outstanding read and + //write posted to the socket simultaneously + m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToAlloc, receiveBufferSize); + + m_Receivepool = new SocketEventPool(numConnections); + m_Sendpool = new SocketEventPool(numConnections); + + msg_pool = new TokenMsgPool(numConnections); + + m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); + } + + #region Client操作 + /// + /// 初始化 + /// + public void Init() + { + // Allocates one large byte buffer which all I/O operations use a piece of. This gaurds + // against memory fragmentation + m_bufferManager.InitBuffer(); + m_clients = new List(); + // preallocate pool of SocketAsyncEventArgs objects + SocketAsyncEventArgs readWriteEventArg; + + for (int i = 0; i < m_maxConnectNum; i++) + { + readWriteEventArg = new SocketAsyncEventArgs(); + readWriteEventArg.Completed += new EventHandler(IO_Completed); + readWriteEventArg.UserToken = new AsyncUserToken(); + // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object + m_bufferManager.SetBuffer(readWriteEventArg); + // add SocketAsyncEventArg to the pool + m_Receivepool.Push(readWriteEventArg); + } + + for (int i = 0; i < m_maxConnectNum; i++) + { + readWriteEventArg = new SocketAsyncEventArgs(); + readWriteEventArg.Completed += new EventHandler(IO_Completed); + readWriteEventArg.UserToken = new AsyncUserToken(); + + //发送是否需要如此设置 TODO + m_bufferManager.SetBuffer(readWriteEventArg); + + m_Sendpool.Push(readWriteEventArg); + } + OutNetLog("初始化完毕"); + } + /// + /// 启动服务 + /// + /// + /// 是否端口重用 + /// + public bool Start() + { + try + { + ClearUserToken(); + + _heartTimer = new System.Timers.Timer(); + _heartTimer.Interval = TimerInterval; + _heartTimer.Elapsed += CheckUpdatetimer_Elapsed; + _heartTimer.AutoReset = true; + _heartTimer.Enabled = true; + OutNetLog("开启定时心跳包"); + + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// 停止服务 + /// + public void Stop() + { + foreach (AsyncUserToken token in m_clients) + { + try + { + token.Socket.Shutdown(SocketShutdown.Both); + } + catch (Exception) { } + } + try + { + for (int i = 0; i < m_clients.Count; i++) + { + m_clients[i].Socket.Shutdown(SocketShutdown.Both); + } + //listenSocket.Shutdown(SocketShutdown.Both); + + for (int i = 0; i < m_clients.Count; i++) + { + m_clients[i].Socket.Close(); + } + } + catch (Exception) { } + + //listenSocket.Close(); + int c_count = m_clients.Count; + ClearUserToken(); + + if (OnClientNumberChange != null) + OnClientNumberChange(-c_count, null); + } + public void CloseClient(AsyncUserToken token) + { + try { token.Socket.Shutdown(SocketShutdown.Both); } + catch (Exception) { } + } + /// + /// 关闭客户端连接 + /// + /// + void CloseClientSocket(SocketAsyncEventArgs e) + { + AsyncUserToken token = e.UserToken as AsyncUserToken; + CloseReady(token); + // 释放SocketAsyncEventArg,以便其他客户端可以重用它们 + ReleaseSocketAsyncEventArgs(e); + } + void CloseReady(AsyncUserToken token) + { + OnDisconnected?.Invoke(token); + RemoveUserToken(token); + //如果有事件,则调用事件,发送客户端数量变化通知 + OnClientNumberChange?.Invoke(-1, token); + // 关闭与客户端关联的套接字 + try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception) { } + token.Socket.Close(); + // 递减计数器以跟踪连接到服务器的客户端总数 + Interlocked.Decrement(ref m_clientCount); + m_maxNumberAcceptedClients.Release(); + } + #endregion + + #region Token管理 + public AsyncUserToken GetAsyncUserTokenForSocket(Socket sk) + { + AsyncUserToken result; + if (_DictSocketAsyncUserToken.TryGetValue(sk, out result)) + return result; + return null; + //return _DictSocketAsyncUserToken.ContainsKey(sk) ? _DictSocketAsyncUserToken[sk] : null; + } + void AddUserToken(AsyncUserToken userToken) + { + lock (_DictSocketAsyncUserToken) + { + m_clients.Add(userToken); + _DictSocketAsyncUserToken.Add(userToken.Socket, userToken); + } + } + void RemoveUserToken(AsyncUserToken userToken) + { + lock (_DictSocketAsyncUserToken) + { + m_clients.Remove(userToken); + _DictSocketAsyncUserToken.Remove(userToken.Socket); + } + } + void ClearUserToken() + { + lock (_DictSocketAsyncUserToken) + { + m_clients.Clear(); + _DictSocketAsyncUserToken.Clear(); + } + } + /// + /// 回收SocketAsyncEventArgs + /// + /// + /// + void ReleaseSocketAsyncEventArgs(SocketAsyncEventArgs saea) + { + //saea.UserToken = null;//TODO + //saea.SetBuffer(null, 0, 0); + //saea.Dispose(); + //↑ 这里不要自作主张去清东西,否则回收回去不可用 + + switch (saea.LastOperation) + { + case SocketAsyncOperation.Receive: + m_Receivepool.Push(saea); + break; + case SocketAsyncOperation.Send: + m_Sendpool.Push(saea); + break; + default: + throw new ArgumentException("ReleaseSocketAsyncEventArgs > The last operation completed on the socket was not a receive or send"); + } + + } + #endregion + + + + #region 连接 + public void StartConnect(string ip, int port, Socket socket, SocketAsyncEventArgs connectEventArg = null) + { + if (connectEventArg == null) + { + connectEventArg = new SocketAsyncEventArgs(); + connectEventArg.Completed += new EventHandler(IO_Completed); + } + else + { + // socket must be cleared since the context object is being reused + connectEventArg.AcceptSocket = null; + //TODO ?? + //这里其实AcceptSocket是服务端用的,非监听的客户端用,本来就为空,清不清理没什么卵用,但是connectEventArg.ConnectSocket是只读的的 + } + + connectEventArg.RemoteEndPoint = new DnsEndPoint(ip, port); + + m_maxNumberAcceptedClients.WaitOne(); + + if (!socket.ConnectAsync(connectEventArg)) + { + ProcessConnect(connectEventArg); + } + } + + private void ProcessConnect(SocketAsyncEventArgs e) + { + try + { + Interlocked.Increment(ref m_clientCount); + + //确保监听结束时,有连接才抛给数据接收 + if (e.ConnectSocket.RemoteEndPoint != null) + { + // Get the socket for the accepted client connection and put it into the + //ReadEventArg object user token + SocketAsyncEventArgs readEventArgs = m_Receivepool.Pop(); + //TODO readEventArgs.UserToken这里的 UserToken 有可能是空 + AsyncUserToken userToken; + if (readEventArgs.UserToken == null) + readEventArgs.UserToken = new AsyncUserToken(); + + userToken = (AsyncUserToken)readEventArgs.UserToken; + userToken.Socket = e.ConnectSocket; + userToken.ConnectTime = DateTime.Now; + userToken.Remote = e.ConnectSocket.RemoteEndPoint; + userToken.IPAddress = ((IPEndPoint)e.ConnectSocket.RemoteEndPoint).Address; + + userToken.RevIndex = MaxRevIndexNum; + userToken.SendIndex = MaxSendIndexNum; + + AddUserToken(userToken); + + OnClientNumberChange?.Invoke(1, userToken); + if (!e.ConnectSocket.ReceiveAsync(readEventArgs)) + { + ProcessReceive(readEventArgs); + } + } + } + catch (Exception me) + { + //RuncomLib.Log.LogUtils.Info(me.Message + "\r\n" + me.StackTrace); + } + + // Accept the next connection request + if (e.SocketError == SocketError.OperationAborted) return; + //StartAccept(e); + } + #endregion + + #region 收发IOCP循环 + /// 当异步接收操作完成时,会调用此方法。 + /// 如果远程主机关闭了连接,则套接字关闭。 + /// 如果接收到数据,则将数据回显到客户端。 + /// + /// + private void ProcessReceive(SocketAsyncEventArgs e) + { + try + { + AsyncUserToken token = (AsyncUserToken)e.UserToken; + if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) + { + lock (token.memoryStream) + { + token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred); + do + { + if (token.memoryStream.Length < 4) break;//包头不完整,继续接收 + long FristBeginPos = token.memoryStream.Position; + + //从Byte池申请 + byte[] lenBytes = ArrayPool.Shared.Rent(4); + + token.memoryStream.Seek(0, SeekOrigin.Begin); + token.memoryStream.Read(lenBytes, 0, 4); + int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4; + + //归还byte[] + ArrayPool.Shared.Return(lenBytes); + + if (packageLen > token.memoryStream.Length - 4) + { + token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin); + break;//长度不够时,退出循环,让程序继续接收 + } + + //申请byte池 一定要记得回收!! + byte[] rev_fromArrayPool = ArrayPool.Shared.Rent(packageLen); + + token.memoryStream.Seek(4, SeekOrigin.Begin); + token.memoryStream.Read(rev_fromArrayPool, 0, packageLen); + token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin); + //从数据池中移除这组数据 + lock (token.memoryStream) + { + int numberOfBytesToRemove = packageLen + 4; + byte[] buf = token.memoryStream.GetBuffer(); + Buffer.BlockCopy(buf, numberOfBytesToRemove, buf, 0, (int)token.memoryStream.Length - numberOfBytesToRemove); + token.memoryStream.SetLength(token.memoryStream.Length - numberOfBytesToRemove); + } + + //用Span内存切片,因为来自ArrayPool的byte长度,可能大于本身申请的长度 + Span rev_span = rev_fromArrayPool; + rev_span = rev_span.Slice(0, packageLen); + DataCallBackReady(token, rev_span); + + //回收(这里依赖DataCallBackReady中,有一次数据拷贝,这个后续还要进一步精进性能优化,否则不能在这里回收,否则影响业务层) + ArrayPool.Shared.Return(rev_fromArrayPool); + } while (token.memoryStream.Length > 4); + } + + //如果返回为False则代表此刻已经完成,不必等待完成端口回调,则直接调用ProcessReceive + if (!token.Socket.ReceiveAsync(e)) + this.ProcessReceive(e); + } + else + { + //清理数据 + token.memoryStream.SetLength(0); + token.memoryStream.Seek(0, SeekOrigin.Begin); + CloseClientSocket(e); + } + } + catch (Exception xe) + { + //RuncomLib.Log.LogUtils.Info(xe.Message + "\r\n" + xe.StackTrace); + } + } + private void ProcessSend(SocketAsyncEventArgs e) + { + if (e.SocketError == SocketError.Success) + { + //TODO + } + else + { + CloseClientSocket(e); + return; + } + ReleaseSocketAsyncEventArgs(e); + SendForMsgPool(); + } + void IO_Completed(object sender, SocketAsyncEventArgs e) + { + // determine which type of operation just completed and call the associated handler + + switch (e.LastOperation) + { + case SocketAsyncOperation.Connect: + ProcessConnect(e); + break; + case SocketAsyncOperation.Receive: + ProcessReceive(e); + break; + case SocketAsyncOperation.Send: + ProcessSend(e); + break; + default: + throw new ArgumentException("The last operation completed on the socket was not a receive or send"); + } + } + #endregion + + #region 发送 + int sendrun = 0; + /// + /// 对外暴露的发送消息 + /// + /// + /// 序列化之后的数据 + public void SendToSocket(Socket sk, int CMDID, byte[] data) + { + AsyncUserToken token = GetAsyncUserTokenForSocket(sk); + SendWithIndex(token, (ushort)CMDID, data); + } + + void SendForMsgPool() + { + //if (flag_SendForMsgPool) return; + try + { + if (sendrun < msg_pool.Count || msg_pool.Count < 1) + return; + + sendrun++; + while (msg_pool.Count > 0) + { + try + { + TokenWithMsg msg = msg_pool.Dequeue(); + //OutNetLog("从信息池取出发送"); + //是心跳包 + if (msg.bHeartbeat) + { + SendHeartbeatMessage(msg.token); + } + else + { + SendMessage(msg.token, msg.CMDID, msg.data); + } + msg = null; + } + catch + { + OutNetLog("==============================================>"); + } + } + sendrun--; + OutNetLog("!!!!!!!!!!!!!!!!!!!!!!!!!!"); + } + catch (Exception ex) + { + OutNetLog(ex.ToString()); + } + + } + + /// + /// 发送心跳包 + /// + /// + void SendHeartbeatMessage(AsyncUserToken token) + { + if (token == null || token.Socket == null || !token.Socket.Connected) + return; + try + { + if (m_Sendpool.Count > 0) + { + SocketAsyncEventArgs myreadEventArgs = m_Sendpool.Pop(); + myreadEventArgs.UserToken = token; + //TODO ????客户端用这里是否应该直接就不设置 + //myreadEventArgs.AcceptSocket = token.Socket; + + //直接写入SocketAsyncEventArgs的Buff + HunterNet_Heartbeat.SetDataToSocketAsyncEventArgs(myreadEventArgs); + + //若不需要等待 + if (!token.Socket.SendAsync(myreadEventArgs)) + { + m_Sendpool.Push(myreadEventArgs); + } + return; + } + else + { + //先压入队列,等待m_Sendpool回收 + msg_pool.Enqueue(new TokenWithMsg() { token = token, bHeartbeat = true }); + //OutNetLog("!!!!压入消息发送队列MSG_Pool"); + return; + } + } + catch (Exception e) + { + OutNetLog(e.ToString()); + } + } + + /// + /// 发送数据并计数 + /// + /// + void SendWithIndex(AsyncUserToken token, ushort CmdID, byte[] data) + { + try + { + //发送数据 + SendMessage(token, CmdID, data); + token.SendIndex = MaxSendIndexNum; + } + catch + { + CloseReady(token); + } + } + + void SendMessage(AsyncUserToken token, ushort CmdID, byte[] data) + { + if (token == null || token.Socket == null || !token.Socket.Connected) + return; + try + { + if (m_Sendpool.Count > 0) + { + SocketAsyncEventArgs myreadEventArgs = m_Sendpool.Pop(); + myreadEventArgs.UserToken = token; + myreadEventArgs.AcceptSocket = token.Socket; + //myreadEventArgs.SetBuffer(message, 0, message.Length); //将数据放置进去. + //更换为CMDID和Data直接写入SocketAsyncEventArgs的Buff + HunterNet_C2S.SetDataToSocketAsyncEventArgs(myreadEventArgs, CmdID, data); + + //若不需要等待 + if (!token.Socket.SendAsync(myreadEventArgs)) + { + m_Sendpool.Push(myreadEventArgs); + } + return; + } + else + { + //先压入队列,等待m_Sendpool回收 + msg_pool.Enqueue(new TokenWithMsg() { token = token, CMDID = CmdID, data = data }); + //OutNetLog("!!!!压入消息发送队列MSG_Pool"); + return; + } + } + catch (Exception e) + { + OutNetLog(e.ToString()); + } + } + #endregion + + #region 处理前预备 + private void DataCallBackReady(AsyncUserToken sk, Span data) + { + //增加接收计数 + sk.RevIndex = MaxRevIndexNum; + + if (data.Length == 1 && data[0] == 0x00)//心跳包 + { + //OutNetLog("收到心跳包"); + //无处理 + } + else + { + try + { + //将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度. + HunterNet_S2C.AnalysisPkgData(data, out ushort CmdID, out ushort Error, out byte[] resultdata); + OnReceive?.Invoke(sk, CmdID, Error, resultdata); + } + catch (Exception ex) + { + OutNetLog("数据解析错误"); + } + } + } + private void OutNetLog(string msg) + { + OnNetLog?.Invoke(msg); + } + #endregion + + #region 心跳包 + /// + /// 发送心跳包 + /// + /// + /// + private void SendHeartbeatWithIndex(AsyncUserToken token) + { + if (token == null || token.Socket == null || !token.Socket.Connected) + return; + try + { + //OutNetLog(DateTime.Now.ToString() + "发送心跳包"); + token.SendIndex = MaxSendIndexNum; + SendHeartbeatMessage(token); + } + catch (Exception e) + { + CloseReady(token); + } + } + /// + /// 心跳包时钟事件 + /// + /// + /// + private void CheckUpdatetimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + for (int i = 0; i < m_clients.Count; i++) + { + //接收服务器数据计数 + m_clients[i].RevIndex--; + if (m_clients[i].RevIndex <= 0) + { + //判定掉线 + CloseReady(m_clients[i]); + return; + } + + //发送计数 + m_clients[i].SendIndex--; + if (m_clients[i].SendIndex <= 0)//需要发送心跳包了 + { + //重置倒计时计数 + m_clients[i].SendIndex = MaxSendIndexNum; + SendHeartbeatWithIndex(m_clients[i]); + } + } + } + #endregion + } +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TokenMsgPool.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TokenMsgPool.cs new file mode 100644 index 0000000..bd171db --- /dev/null +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/IOCPMode/TokenMsgPool.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; + +namespace HaoYueNet.ClientNetwork.IOCPMode +{ + public class TokenWithMsg + { + public AsyncUserToken token; + public ushort CMDID; + //public UInt16 Error; + public byte[] data; + public bool bHeartbeat; + } + + public class TokenMsgPool + { + //Stack msg_pool; + Queue msg_pool; + + public TokenMsgPool(int capacity) + { + msg_pool = new Queue(capacity); + } + + /// + /// 向 Queue 的末尾添加一个对象。 + /// + /// + public void Enqueue(TokenWithMsg item) + { + lock (msg_pool) + { + msg_pool.Enqueue(item); + } + } + + //移除并返回在 Queue 的开头的对象。 + public TokenWithMsg Dequeue() + { + lock (msg_pool) + { + return msg_pool.Dequeue(); + } + } + + public int Count + { + get { return msg_pool.Count; } + } + + public void Clear() + { + msg_pool.Clear(); + } + } + + /* + public class TokenWithMsg + { + public AsyncUserToken token; + public byte[] message; + } + + public class TokenMsgPool + { + //Stack msg_pool; + Queue msg_pool; + + public TokenMsgPool(int capacity) + { + //msg_pool = new Stack(capacity); + msg_pool = new Queue(capacity); + } + + //public void Push(TokenWithMsg item) + //{ + // if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); } + // lock (msg_pool) + // { + // msg_pool.Push(item); + // } + //} + + /// + /// 向 Queue 的末尾添加一个对象。 + /// + /// + public void Enqueue(TokenWithMsg item) + { + lock (msg_pool) + { + msg_pool.Enqueue(item); + } + } + + //移除并返回在 Queue 的开头的对象。 + public TokenWithMsg Dequeue() + { + lock (msg_pool) + { + return msg_pool.Dequeue(); + } + } + + //// Removes a SocketAsyncEventArgs instance from the pool + //// and returns the object removed from the pool + //public TokenWithMsg Pop() + //{ + // lock (msg_pool) + // { + // return msg_pool.Pop(); + // } + //} + + // The number of SocketAsyncEventArgs instances in the pool + public int Count + { + get { return msg_pool.Count; } + } + + public void Clear() + { + msg_pool.Clear(); + } + } + */ +} diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperCore.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperCore.cs index 7e21971..c057ac8 100644 --- a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperCore.cs +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperCore.cs @@ -4,15 +4,14 @@ using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; -using static HaoYueNet.ClientNetwork.Standard2.BaseData; +using static HaoYueNet.ClientNetwork.BaseData; -namespace HaoYueNet.ClientNetwork.Standard2 +namespace HaoYueNet.ClientNetwork { public class NetworkHelperCore { private Socket client; - ////响应倒计时计数最大值 //private static int MaxRevIndexNum = 6; @@ -26,9 +25,9 @@ namespace HaoYueNet.ClientNetwork.Standard2 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; @@ -39,7 +38,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 public static int LastConnectPort; public bool bDetailedLog = false; - public bool Init(string IP, int port, bool isHadDetailedLog = true, bool bBindReuseAddress = false, int bBindport = 0) + public bool Init(string IP, int port,bool isHadDetailedLog = true, bool bBindReuseAddress = false,int bBindport = 0,AddressFamily addressFamily = AddressFamily.InterNetwork) { LogOut("==>初始化网络核心"); @@ -47,7 +46,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 RevIndex = MaxRevIndexNum; SendIndex = MaxSendIndexNum; - client = new Socket(SocketType.Stream, ProtocolType.Tcp); + client = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); if (bBindReuseAddress) { client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -64,7 +63,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 //带回调的 try { - if (bDetailedLog) + if(bDetailedLog) LogOut("连接到远程IP " + IP + ":" + port); else LogOut("连接到远程服务"); @@ -151,7 +150,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 /// private void SendWithIndex(byte[] data) { - lock (sendLock) + lock (sendLock) { //增加发送计数 SendIndex = MaxSendIndexNum; @@ -160,40 +159,13 @@ namespace HaoYueNet.ClientNetwork.Standard2 } } - ////拼接头长度 - //private byte[] SendDataWithHead(byte[] message) - //{ - - // MemoryStream memoryStream = new MemoryStream();//创建一个内存流 - - // byte[] BagHead = BitConverter.GetBytes(message.Length + 4);//往字节数组中写入包头(包头自身的长度和消息体的长度)的长度 - - // memoryStream.Write(BagHead, 0, BagHead.Length);//将包头写入内存流 - - // memoryStream.Write(message, 0, message.Length);//将消息体写入内存流 - - // byte[] HeadAndBody = memoryStream.ToArray();//将内存流中的数据写入字节数组 - - // memoryStream.Close();//关闭内存 - // memoryStream.Dispose();//释放资源 - - // return HeadAndBody; - //} - /// /// 供外部调用 发送消息 /// /// /// 序列化之后的数据 - public void SendToServer(int CMDID, byte[] data) + public void SendToServer(int CMDID,byte[] data) { - //LogOut("准备数据 CMDID=> "+CMDID); - /* - HunterNet_C2S _c2sdata = new HunterNet_C2S(); - _c2sdata.HunterNetCoreCmdID = CMDID; - _c2sdata.HunterNetCoreData = ByteString.CopyFrom(data); - byte[] _finaldata = Serizlize(_c2sdata); - */ byte[] _finaldata = HunterNet_C2S.CreatePkgData((ushort)CMDID, data); SendToSocket(_finaldata); } @@ -236,7 +208,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 { OnCloseReady(); } - + private void DataCallBackReady(byte[] data) { @@ -250,17 +222,10 @@ namespace HaoYueNet.ClientNetwork.Standard2 return; } - /* - HunterNet_S2C _c2s = DeSerizlize(data); - - OnReceiveData(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray()); - */ - HunterNet_S2C.AnalysisPkgData(data, out ushort CmdID, out ushort Error, out byte[] resultdata); OnReceiveData(CmdID, Error, resultdata); } - MemoryStream reciveMemoryStream = new MemoryStream();//开辟一个反复使用的内存流 byte[] reciveBuffer = new byte[1024 * 1024 * 2];//开辟一个反复使用的byte[] private void Recive(object o) @@ -282,7 +247,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 return; } } - catch (Exception ex) + catch(Exception ex) { //清理数据 reciveMemoryStream.SetLength(0); @@ -316,12 +281,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 //↓↓↓↓↓↓↓↓ ↓↓↓ if (getData.Length - StartIndex < HeadLength || HeadLength == -1) { - /* 一种清空流的方式 - memoryStream.Close();//关闭内存流 - memoryStream.Dispose();//释放内存资源 - memoryStream = new MemoryStream();//创建新的内存流 - */ - //流复用的方式 不用重新new申请 reciveMemoryStream.Position = 0; reciveMemoryStream.SetLength(0); @@ -331,16 +290,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 } else { - //把头去掉,就可以吃了,蛋白质是牛肉的六倍 - //DataCallBackReady(getData.Skip(StartIndex+4).Take(HeadLength-4).ToArray()); - int CoreLenght = HeadLength - 4; - - //改为Array.Copy 提升效率 - //byte[] retData = new byte[CoreLenght]; - //Array.Copy(getData, StartIndex + 4, retData, 0, CoreLenght); - //DataCallBackReady(retData); - //用Span Span getData_span = getData; getData_span = getData_span.Slice(StartIndex + 4, CoreLenght); @@ -378,7 +328,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 public void LogOut(string Msg) { - //Console.WriteLine(Msg); OnLogOut?.Invoke(Msg); } diff --git a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperP2PCore.cs b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperP2PCore.cs index ce9106d..b3e2b52 100644 --- a/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperP2PCore.cs +++ b/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2/NetworkHelperP2PCore.cs @@ -3,9 +3,9 @@ using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; -using static HaoYueNet.ClientNetwork.Standard2.BaseData; +using static HaoYueNet.ClientNetwork.BaseData; -namespace HaoYueNet.ClientNetwork.Standard2 +namespace HaoYueNet.ClientNetwork { public class NetworkHelperP2PCore { @@ -18,24 +18,22 @@ namespace HaoYueNet.ClientNetwork.Standard2 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) + public void Init(bool bBindReuseAddress = false,int bBindport = 0, AddressFamily addressFamily = AddressFamily.InterNetwork) { - LogOut("==>初始化网络核心"); - RevIndex = MaxRevIndexNum; SendIndex = MaxSendIndexNum; - client = new Socket(SocketType.Stream, ProtocolType.Tcp); + client = new Socket(addressFamily,SocketType.Stream, ProtocolType.Tcp); if (bBindReuseAddress) { client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); @@ -127,26 +125,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 client.Send(data); } - ////拼接头长度 - //private byte[] SendDataWithHead(byte[] message) - //{ - - // MemoryStream memoryStream = new MemoryStream();//创建一个内存流 - - // byte[] BagHead = BitConverter.GetBytes(message.Length + 4);//往字节数组中写入包头(包头自身的长度和消息体的长度)的长度 - - // memoryStream.Write(BagHead, 0, BagHead.Length);//将包头写入内存流 - - // memoryStream.Write(message, 0, message.Length);//将消息体写入内存流 - - // byte[] HeadAndBody = memoryStream.ToArray();//将内存流中的数据写入字节数组 - - // memoryStream.Close();//关闭内存 - // memoryStream.Dispose();//释放资源 - - // return HeadAndBody; - //} - /// /// 供外部调用 发送消息 /// @@ -155,13 +133,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 /// public void SendToSocket(int CMDID, int ERRCODE, byte[] data) { - //LogOut("准备数据 CMDID=> "+CMDID); - /*HunterNet_S2C _s2sdata = new HunterNet_S2C(); - _s2sdata.HunterNetCoreCmdID = CMDID; - _s2sdata.HunterNetCoreERRORCode = ERRCODE; - _s2sdata.HunterNetCoreData = ByteString.CopyFrom(data); - byte[] _finaldata = Serizlize(_s2sdata);*/ - byte[] _finaldata = HunterNet_S2C.CreatePkgData((ushort)CMDID, (ushort)ERRCODE, data); SendToSocket(_finaldata); } @@ -185,24 +156,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 /// public event delegate_str OnLogOut; - ///// - ///// 用于调用者回调的虚函数 - ///// - ///// - //public virtual void DataCallBack(int CMDID,int ERRCODE,byte[] data) - //{ - - //} - - ///// - ///// 断开连接 - ///// - ///// - //public virtual void OnClose() - //{ - - //} - /// /// 做好处理的连接管理 /// @@ -225,7 +178,7 @@ namespace HaoYueNet.ClientNetwork.Standard2 { OnCloseReady(); } - + private void DataCallBackReady(byte[] data) { @@ -239,16 +192,12 @@ namespace HaoYueNet.ClientNetwork.Standard2 return; } - /* - HunterNet_S2C _c2s = DeSerizlize(data); - OnDataCallBack(_c2s.HunterNetCoreCmdID, _c2s.HunterNetCoreERRORCode, _c2s.HunterNetCoreData.ToArray()); - */ HunterNet_S2C.AnalysisPkgData(data, out ushort CmdID, out ushort Error, out byte[] resultdata); OnDataCallBack(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) { var client = o as Socket; @@ -302,12 +251,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 //↓↓↓↓↓↓↓↓ ↓↓↓ if (getData.Length - StartIndex < HeadLength || HeadLength == -1) { - /* 一种清空流的方式 - memoryStream.Close();//关闭内存流 - memoryStream.Dispose();//释放内存资源 - memoryStream = new MemoryStream();//创建新的内存流 - */ - //流复用的方式 不用重新new申请 reciveMemoryStream.Position = 0; reciveMemoryStream.SetLength(0); @@ -317,23 +260,14 @@ namespace HaoYueNet.ClientNetwork.Standard2 } else { - //把头去掉,就可以吃了,蛋白质是牛肉的六倍 - //DataCallBackReady(getData.Skip(StartIndex+4).Take(HeadLength-4).ToArray()); - int CoreLenght = HeadLength - 4; - //改为Array.Copy 提升效率 - //byte[] retData = new byte[CoreLenght]; - //Array.Copy(getData, StartIndex + 4, retData, 0, CoreLenght); - //DataCallBackReady(retData); - - byte[] getData_span = new byte[CoreLenght]; - //DATA - Buffer.BlockCopy(getData, StartIndex + 4, getData_span, 0, CoreLenght); - DataCallBackReady(getData_span); + //用Span + Span getData_span = getData; + getData_span = getData_span.Slice(StartIndex + 4, CoreLenght); + DataCallBackReady(getData_span.ToArray()); StartIndex += HeadLength;//当读取一条完整的数据后,读取数据的起始下标应为当前接受到的消息体的长度(当前数据的尾部或下一条消息的首部) - } } } @@ -364,7 +298,6 @@ namespace HaoYueNet.ClientNetwork.Standard2 public void LogOut(string Msg) { - //Console.WriteLine(Msg); OnLogOut(Msg); }