private void ProcessAccept(SocketAsyncEventArgs e) { if (GetIDByEndPoint == null) { throw new ArgumentException("The function GetIDByEndPoint can not be null!"); } if (e.LastOperation != SocketAsyncOperation.Accept) //检查上一次操作是否是Accept,不是就返回 { return; } string UID = GetIDByEndPoint(e.AcceptSocket.RemoteEndPoint as IPEndPoint); //根据IP获取用户的UID if (string.IsNullOrEmpty(UID)) { return; } if (readWritePool.BusyPoolContains(UID)) //判断现在的用户是否已经连接,避免同一用户开两个连接 { return; } SocketAsyncEventArgsWithId readEventArgsWithId = this.readWritePool.Pop(UID); AsyncUserToken userToken = new AsyncUserToken { UID = UID, Socket = e.AcceptSocket, ConnectTime = DateTime.Now, FreshTime = DateTime.Now, Remote = e.AcceptSocket.RemoteEndPoint as IPEndPoint }; readEventArgsWithId.ReceiveSAEA.UserToken = userToken; readEventArgsWithId.SendSAEA.UserToken = userToken; //激活接收 if (!e.AcceptSocket.ReceiveAsync(readEventArgsWithId.ReceiveSAEA)) { ProcessReceive(readEventArgsWithId.ReceiveSAEA); } Interlocked.Increment(ref this.numConnections); OnClientNumberChange?.Invoke(1, userToken); this.StartAccept(e); }
private void ProcessSend(SocketAsyncEventArgs e) { if (OnSended == null) { throw new ArgumentException("The function OnSended can not be null!"); } if (e.LastOperation != SocketAsyncOperation.Send) { return; } AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0) { OnSended(token, e.SocketError); } else { this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID); } }
private void ProcessReceive(SocketAsyncEventArgs e) { if (!(e.BytesTransferred > 0 && e.SocketError == SocketError.Success)) { CloseClientSocket(((MySocketAsyncEventArgs)e).UID); return; } if (GetPackageLength == null) { throw new ArgumentException("The function GetPackageLength can not be null!"); } if (e.LastOperation != SocketAsyncOperation.Receive) { return; } AsyncUserToken token = (AsyncUserToken)e.UserToken; token.FreshTime = DateTime.Now; byte[] data = new byte[e.BytesTransferred]; Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred); lock (token.Buffer) { token.Buffer.AddRange(data); } int headLen = 0; int packageLen = 0; //如果当客户发送大数据流的时候,e.BytesTransferred的大小就会比客户端发送过来的要小, //需要分多次接收.所以收到包的时候,先判断包头的大小.够一个完整的包再处理. //如果客户短时间内发送多个小数据包时, 服务器可能会一次性把他们全收了. //这样如果没有一个循环来控制,那么只会处理第一个包, //剩下的包全部留在token.Buffer中了,只有等下一个数据包过来后,才会放出一个来. do { packageLen = GetPackageLength(token.Buffer.ToArray(), out headLen); //获取包头标记的数据长度以及包头的长度 if (packageLen > token.Buffer.Count - headLen) { break; } //如果实际数据的长度小于数据中标记的长度,则退出循环,让程序继续接收 byte[] rev = token.Buffer.GetRange(headLen, packageLen).ToArray(); //包够长时,则提取出来,交给后面的程序去处理 //从数据池中移除这组数据,若是同时接收了多个数据包,则token.Buffer中仍会存在数据,循环会继续 lock (token.Buffer) { token.Buffer.RemoveRange(0, packageLen + headLen); } OnMsgReceived?.Invoke(token, rev); } while (token.Buffer.Count > headLen); if (!token.Socket.ReceiveAsync(e)) { ProcessReceive(e); } }