From f2e0279fd9144bf43f1c82d3e50b6784baac889c Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Fri, 29 Mar 2024 17:49:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E6=97=B6=E4=B8=8D=E4=BD=BF=E7=94=A8Me?= =?UTF-8?q?moryStream=EF=BC=8C=E4=BC=98=E5=8C=96=E5=90=8E=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E4=BD=BF=E7=94=A8=EF=BC=8C=E4=BB=A5=E5=8F=8A=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E5=BA=93=E7=9A=84=E5=8E=9F=E7=94=9FListener?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NetworkHelperCore.cs | 12 +- .../NetworkHelperCore_ListenerMode.cs | 165 +++++++++++------- .../NetWork/AsyncUserToken.cs | 8 +- .../SourceMode/TcpSaeaServer_SourceMode.cs | 41 +++-- .../NetWork/TcpSaeaServer.cs | 116 ++++++------ 5 files changed, 200 insertions(+), 142 deletions(-) diff --git a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs index a92d0ed..977e689 100644 --- a/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs +++ b/NetLib/HaoYueNet.ClientNetwork/NetworkHelperCore.cs @@ -141,16 +141,20 @@ namespace HaoYueNet.ClientNetwork //LogOut("发送心跳包"); } + object sendLock = new object(); /// /// 发送数据并计数 /// /// private void SendWithIndex(byte[] data) { - //增加发送计数 - SendIndex = MaxSendIndexNum; - //发送数据 - client.Send(data); + lock (sendLock) + { + //增加发送计数 + SendIndex = MaxSendIndexNum; + //发送数据 + client.Send(data); + } } ////拼接头长度 diff --git a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs index d09d385..be178e1 100644 --- a/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs +++ b/NetLib/HaoYueNet.ClientNetwork/OtherMode/NetworkHelperCore_ListenerMode.cs @@ -7,7 +7,7 @@ namespace HaoYueNet.ClientNetwork.OtherMode public class NetworkHelperCore_ListenerMode { private Socket serversocket; - private Socket client; + private Dictionary mDictHandleClient; //响应倒计时计数最大值 private static int MaxRevIndexNum = 50; @@ -28,65 +28,109 @@ namespace HaoYueNet.ClientNetwork.OtherMode public void Init(int port) { + mDictHandleClient = new Dictionary(); + LogOut("==>初始化NetworkHelperCore_ListenerMode"); serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port); serversocket.Bind(endPoint); // 绑定 serversocket.Listen(1); - client = serversocket.Accept(); // 接收客户端连接 - OnConnected?.Invoke(true); - Console.WriteLine("客户端连接成功 信息: " + client.AddressFamily.ToString()); - Thread revThread = new Thread(Recive); - revThread.Start(client); + //client = serversocket.Accept(); // 接收客户端连接 + //OnConnected?.Invoke(true); + //Console.WriteLine("客户端连接成功 信息: " + client.AddressFamily.ToString()); + //Thread revThread = new Thread(Recive); + //revThread.Start(client); + + Task task = new Task(() => + { + while (true) + { + Socket newclient; + try + { + newclient = serversocket.Accept(); // 接收客户端连接 + } + catch + { + break; + } + AddDictSocket(newclient); + OnConnected?.Invoke(newclient); + Console.WriteLine("客户端连接成功 信息: " + newclient.AddressFamily.ToString()); + Thread revThread = new Thread(Recive); + revThread.Start(newclient); + } + }); + task.Start(); } + #region + + /// + /// 追加Socket返回下标 + /// + /// + /// + public void AddDictSocket(Socket socket) + { + if (socket == null) + return; + lock (mDictHandleClient) + { + mDictHandleClient[socket.Handle] = socket; + } + } + + public void RemoveDictSocket(Socket socket) + { + if (socket == null) + return; + lock (mDictHandleClient) + { + if (!mDictHandleClient.ContainsKey(socket.Handle)) + return; + mDictHandleClient.Remove(socket.Handle); + } + } + #endregion + ~NetworkHelperCore_ListenerMode() { - client.Close(); + nint[] keys = mDictHandleClient.Keys.ToArray(); + for (uint i = 0; i < keys.Length; i++) + { + mDictHandleClient[keys[i]].Close(); + } + mDictHandleClient.Clear(); } - private void SendToSocket(byte[] data) + private void SendToSocket(Socket socket, byte[] data) { //已拼接包长度,这里不再需要拼接长度 //data = SendDataWithHead(data); try { - SendWithIndex(data); + SendWithIndex(socket,data); } catch (Exception ex) { //连接断开 - OnCloseReady(); + OnCloseReady(socket); return; } //LogOut("发送消息,消息长度=> "+data.Length); } - private void SendHeartbeat() - { - try - { - SendWithIndex(HeartbeatData); - } - catch (Exception ex) - { - //连接断开 - OnCloseReady(); - return; - } - //LogOut("发送心跳包"); - } - /// /// 发送数据并计数 /// /// - private void SendWithIndex(byte[] data) + private void SendWithIndex(Socket socket,byte[] data) { //增加发送计数 SendIndex = MaxSendIndexNum; //发送数据 - client.Send(data); + socket.Send(data); } /// @@ -94,56 +138,60 @@ namespace HaoYueNet.ClientNetwork.OtherMode /// /// /// 序列化之后的数据 - public void SendToClient(byte[] data) + public void SendToClient(Socket socket, byte[] data) { //LogOut("准备数据 data=> "+data); - SendToSocket(data); + SendToSocket(socket, data); } #region 事件定义 - public delegate void OnReceiveDataHandler(byte[] data); - public delegate void OnConnectedHandler(bool IsConnected); - public delegate void OnCloseHandler(); - public delegate void OnLogOutHandler(string Msg); + public delegate void OnConnectedHandler(Socket socket); + + public delegate void OnReceiveDataHandler(Socket sk, byte[] data); + + public delegate void OnDisconnectHandler(Socket sk); + + public delegate void OnNetLogHandler(string msg); #endregion public event OnConnectedHandler OnConnected; - public event OnReceiveDataHandler OnReceiveData; - public event OnCloseHandler OnClose; - /// - /// 网络库调试日志输出 - /// - public event OnLogOutHandler OnLogOut; + + public event OnReceiveDataHandler OnReceive; + + public event OnDisconnectHandler OnDisconnected; + + public event OnNetLogHandler OnNetLog; /// /// 做好处理的连接管理 /// - private void OnCloseReady() + private void OnCloseReady(Socket socket) { LogOut("关闭连接"); //关闭Socket连接 - client.Close(); - OnClose?.Invoke(); + socket.Close(); + RemoveDictSocket(socket); + OnDisconnected?.Invoke(socket); } /// /// 主动关闭连接 /// - public void CloseConntect() + public void CloseConntect(Socket socket) { - OnCloseReady(); + OnCloseReady(socket); } - private void DataCallBackReady(byte[] data) + private void DataCallBackReady(Socket socket,byte[] data) { //增加接收计数 RevIndex = MaxRevIndexNum; - OnReceiveData(data); + OnReceive(socket,data); } - MemoryStream memoryStream = new MemoryStream();//开辟一个内存流 private void Recive(object o) { + MemoryStream memoryStream = new MemoryStream();//开辟一个内存流 var client = o as Socket; //MemoryStream memoryStream = new MemoryStream();//开辟一个内存流 @@ -162,20 +210,17 @@ namespace HaoYueNet.ClientNetwork.OtherMode catch (Exception ex) { //远程主机强迫关闭了一个现有的连接 - OnCloseReady(); + OnCloseReady(client); return; //断开连接 } - memoryStream.Write(buffer, 0, effective);//将接受到的数据写入内存流中 - while (true) + if (effective > 0)//如果接受到的消息不为0(不为空) { - if (effective > 0)//如果接受到的消息不为0(不为空) - { - DataCallBackReady(memoryStream.ToArray()); - //流复用的方式 不用重新new申请 - memoryStream.Position = 0; - memoryStream.SetLength(0); - } + memoryStream.Write(buffer, 0, effective);//将接受到的数据写入内存流中 + DataCallBackReady(client, memoryStream.ToArray()); + //流复用的方式 不用重新new申请 + memoryStream.Position = 0; + memoryStream.SetLength(0); } } } @@ -183,12 +228,8 @@ namespace HaoYueNet.ClientNetwork.OtherMode public void LogOut(string Msg) { //Console.WriteLine(Msg); - OnLogOut?.Invoke(Msg); + OnNetLog?.Invoke(Msg); } - public Socket GetClientSocket() - { - return client; - } } } diff --git a/NetLib/HaoYueNet.ServerNetwork/NetWork/AsyncUserToken.cs b/NetLib/HaoYueNet.ServerNetwork/NetWork/AsyncUserToken.cs index 1b6df2c..9215aca 100644 --- a/NetLib/HaoYueNet.ServerNetwork/NetWork/AsyncUserToken.cs +++ b/NetLib/HaoYueNet.ServerNetwork/NetWork/AsyncUserToken.cs @@ -33,14 +33,14 @@ namespace HaoYueNet.ServerNetwork /// /// 数据缓存区 /// - //public List Buffer { get; set; } + public List Buffer { get; set; } - public MemoryStream memoryStream { get; set; } + //public MemoryStream memoryStream { get; set; } public AsyncUserToken() { - //this.Buffer = new List(); - this.memoryStream = new MemoryStream(); + this.Buffer = new List(); + //this.memoryStream = new MemoryStream(); } /// /// 响应倒计时计数 diff --git a/NetLib/HaoYueNet.ServerNetwork/NetWork/SourceMode/TcpSaeaServer_SourceMode.cs b/NetLib/HaoYueNet.ServerNetwork/NetWork/SourceMode/TcpSaeaServer_SourceMode.cs index e87ff81..e760ef7 100644 --- a/NetLib/HaoYueNet.ServerNetwork/NetWork/SourceMode/TcpSaeaServer_SourceMode.cs +++ b/NetLib/HaoYueNet.ServerNetwork/NetWork/SourceMode/TcpSaeaServer_SourceMode.cs @@ -378,22 +378,35 @@ namespace HaoYueNet.ServerNetwork if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { //读取数据 - lock(token.memoryStream) + + //读取数据 + byte[] data = new byte[e.BytesTransferred]; + Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred); + lock (token.Buffer) + //lock(token.memoryStream) { - //token.Buffer.AddRange(data); - token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred); + token.Buffer.AddRange(data); + //token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred); + do + { + + DataCallBackReady(token, data); + //从数据池中移除这组数据 + lock (token.Buffer) + { + token.Buffer.Clear(); + } + + //DataCallBackReady(token, token.memoryStream.ToArray()); + ////流复用的方式 不用重新new申请 + //token.memoryStream.Position = 0; + //token.memoryStream.SetLength(0); + + //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收. + //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了. + //} while (token.memoryStream.Length > 0); + } while (token.Buffer.Count > 4); } - do - { - - DataCallBackReady(token,token.memoryStream.ToArray()); - //流复用的方式 不用重新new申请 - token.memoryStream.Position = 0; - token.memoryStream.SetLength(0); - - //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收. - //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了. - } while (token.memoryStream.Length > 0); //继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明 if (!token.Socket.ReceiveAsync(e)) diff --git a/NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs b/NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs index 901cc91..56f473e 100644 --- a/NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs +++ b/NetLib/HaoYueNet.ServerNetwork/NetWork/TcpSaeaServer.cs @@ -378,68 +378,68 @@ namespace HaoYueNet.ServerNetwork 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) + byte[] data = new byte[e.BytesTransferred]; + Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred); + lock (token.Buffer) + //lock(token.memoryStream) { - //token.Buffer.AddRange(data); - token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred); - } - do - { - //如果包头不完整 - //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; - byte[] lenBytes = new byte[4]; - token.memoryStream.Seek(0, SeekOrigin.Begin); - token.memoryStream.Read(lenBytes,0,4); - int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4; - if (packageLen > token.memoryStream.Length - 4) - { //长度不够时,退出循环,让程序继续接收 - break; - } - - //包够长时,则提取出来,交给后面的程序去处理 - //byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray(); - - byte[] rev = new byte[packageLen]; - token.memoryStream.Seek(4, SeekOrigin.Begin); - token.memoryStream.Read(rev, 0, packageLen); - - ////从数据池中移除这组数据 - //lock (token.Buffer) - //{ - // token.Buffer.RemoveRange(0, packageLen + 4); - //} - - token.memoryStream.Seek(FristBeginPos, SeekOrigin.Begin); - //从数据池中移除这组数据 - lock (token.memoryStream) + token.Buffer.AddRange(data); + //token.memoryStream.Write(e.Buffer, e.Offset, e.BytesTransferred); + do { - 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); - } + //如果包头不完整 + if (token.Buffer.Count < 4) + //if (token.memoryStream.Length < 4) + break; - DataCallBackReady(token, rev); + //判断包的长度 + byte[] lenBytes = token.Buffer.GetRange(0, 4).ToArray(); + int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4; + if (packageLen > token.Buffer.Count - 4) + { //长度不够时,退出循环,让程序继续接收 + break; + } - //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收. - //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了. - //} while (token.Buffer.Count > 4); - } while (token.memoryStream.Length > 4); + //long FristBeginPos = token.memoryStream.Position; + //byte[] lenBytes = new byte[4]; + //token.memoryStream.Seek(0, SeekOrigin.Begin); + //token.memoryStream.Read(lenBytes, 0, 4); + //int packageLen = BitConverter.ToInt32(lenBytes, 0) - 4; + //if (packageLen > token.memoryStream.Length - 4) + //{ //长度不够时,退出循环,让程序继续接收 + // break; + //} + + //包够长时,则提取出来,交给后面的程序去处理 + byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray(); + + //byte[] rev = new byte[packageLen]; + //token.memoryStream.Seek(4, SeekOrigin.Begin); + //token.memoryStream.Read(rev, 0, packageLen); + + //从数据池中移除这组数据 + lock (token.Buffer) + { + token.Buffer.RemoveRange(0, packageLen + 4); + } + + //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); + //} + + DataCallBackReady(token, rev); + + //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收. + //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了. + } while (token.Buffer.Count > 4); + //} while (token.memoryStream.Length > 4); + } //继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明 if (!token.Socket.ReceiveAsync(e))