// This method is invoked when an asynchronous send operation completes.
 // The method issues another receive on the socket to read any additional
 // data sent from the client
 //
 // <param name="e"></param>
 private void ProcessSend(SocketAsyncEventArgs e)
 {
     if (e.SocketError == SocketError.Success)
     {
         // done echoing data back to the client
         AsyncUserToken token = (AsyncUserToken)e.UserToken;
         // read the next block of data send from the client
         bool willRaiseEvent = token.Socket.ReceiveAsync(e);
         if (!willRaiseEvent)
         {
             ProcessReceive(e);
         }
     }
     else
     {
         CloseClientSocket(e);
     }
 }
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            try
            {
                Interlocked.Increment(ref _clientCount);
                // Get the socket for the accepted client connection and put it into the
                //ReadEventArg object user token
                SocketAsyncEventArgs readEventArgs = _pool.Pop();
                AsyncUserToken       userToken     = (AsyncUserToken)readEventArgs.UserToken;
                userToken.Socket      = e.AcceptSocket;
                userToken.ConnectTime = DateTime.Now;
                userToken.Remote      = e.AcceptSocket.RemoteEndPoint;
                userToken.IPAddress   = ((IPEndPoint)(e.AcceptSocket.RemoteEndPoint)).Address;

                lock (clients) { clients.Add(userToken); }

                if (ClientNumberChange != null)
                {
                    ClientNumberChange(1, userToken);
                }
                if (!e.AcceptSocket.ReceiveAsync(readEventArgs))
                {
                    ProcessReceive(readEventArgs);
                }
            }
            catch (Exception me)
            {
                throw;
            }

            // Accept the next connection request
            if (e.SocketError == SocketError.OperationAborted)
            {
                return;
            }
            StartAccept(e);
        }
        //关闭客户端
        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = e.UserToken as AsyncUserToken;

            lock (clients) { clients.Remove(token); }
            //如果有事件,则调用事件,发送客户端数量变化通知
            if (ClientNumberChange != null)
            {
                ClientNumberChange(-1, token);
            }
            // close the socket associated with the client
            try
            {
                token.Socket.Shutdown(SocketShutdown.Send);
            }
            catch (Exception) { }
            token.Socket.Close();
            // decrement the counter keeping track of the total number of clients connected to the server
            Interlocked.Decrement(ref _clientCount);
            m_maxNumberAcceptedClients.Release();
            // Free the SocketAsyncEventArg so they can be reused by another client
            e.UserToken = new AsyncUserToken();
            _pool.Push(e);
        }
        // This method is invoked when an asynchronous receive operation completes.
        // If the remote host closed the connection, then the socket is closed.
        // If data was received then the data is echoed back to the client.
        //
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="e"></param>
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            try
            {
                // check if the remote host closed the connection
                AsyncUserToken token = (AsyncUserToken)e.UserToken;
                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)
                    {
                        token.Buffer.AddRange(data);
                    }
                    //注意:你一定会问,这里为什么要用do-while循环?
                    //如果当客户发送大数据流的时候,e.BytesTransferred的大小就会比客户端发送过来的要小,
                    //需要分多次接收.所以收到包的时候,先判断包头的大小.够一个完整的包再处理.
                    //如果客户短时间内发送多个小数据包时, 服务器可能会一次性把他们全收了.
                    //这样如果没有一个循环来控制,那么只会处理第一个包,
                    //剩下的包全部留在token.Buffer中了,只有等下一个数据包过来后,才会放出一个来.
                    do
                    {
                        //判断包的长度
                        byte[] lenBytes   = token.Buffer.GetRange(0, 4).ToArray();
                        int    packageLen = BitConverter.ToInt32(lenBytes, 0);
                        if (packageLen > token.Buffer.Count - 4)
                        {   //长度不够时,退出循环,让程序继续接收
                            break;
                        }

                        //包够长时,则提取出来,交给后面的程序去处理
                        byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray();
                        //从数据池中移除这组数据
                        lock (token.Buffer)
                        {
                            token.Buffer.RemoveRange(0, packageLen + 4);
                        }
                        //将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度.
                        if (ReceiveClientData != null)
                        {
                            ReceiveClientData(token, rev);
                        }
                        //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收.
                        //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了.
                    } while (token.Buffer.Count > 4);

                    //继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明
                    if (!token.Socket.ReceiveAsync(e))
                    {
                        this.ProcessReceive(e);
                    }
                }
                else
                {
                    CloseClientSocket(e);
                }
            }
            catch (Exception xe)
            {
                throw;
            }
        }