Example #1
0
        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);
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
            }
        }