Пример #1
0
        void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.OperationAborted)
            {
                Stop();
                return;
            }

            try
            {
                // create SocketAsyncEventArgs for this client
                SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                args.Completed += IO_Completed;
                args.UserToken  = new AsyncUserToken();

                // assign chunk of big buffer for max performance (see BigBuffer.cs comments)
                if (bigBuffer.Assign(args))
                {
                    // Get the socket for the accepted client connection and put it into the
                    //ReadEventArg object user token
                    AsyncUserToken userToken = (AsyncUserToken)args.UserToken;
                    userToken.Socket       = e.AcceptSocket;
                    userToken.ConnectTime  = DateTime.Now;
                    userToken.Remote       = e.AcceptSocket.RemoteEndPoint;
                    userToken.IpAddress    = ((IPEndPoint)(e.AcceptSocket.RemoteEndPoint)).Address;
                    userToken.connectionId = NextConnectionId();

                    clients[userToken.connectionId] = userToken;

                    OnClientConnected(userToken);

                    if (!e.AcceptSocket.ReceiveAsync(args))
                    {
                        ProcessReceive(args);
                    }
                }
                else
                {
                    Debug.LogError("Server.ProcessAccept: failed to assign buffer.");
                }
            }
            catch (Exception exception)
            {
                Debug.LogError("Server.ProcessAccept failed: " + exception);
            }

            StartAccept(e);
        }
Пример #2
0
        void CloseClientSocket(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = (AsyncUserToken)e.UserToken;

            clients.TryRemove(token.connectionId, out AsyncUserToken temp);

            // close the socket associated with the client
            try
            {
                token?.Socket.Shutdown(SocketShutdown.Both);
            }
            catch (Exception) { }
            token?.Socket.Close();

            // call disconnected event
            OnClientDisconnected(token);

            // free buffer chunk
            bigBuffer.Free(e);
        }
Пример #3
0
        public void Stop()
        {
            foreach (KeyValuePair <int, AsyncUserToken> kvp in clients)
            {
                AsyncUserToken token = kvp.Value;
                try
                {
                    token.Socket.Shutdown(SocketShutdown.Both);
                    OnClientDisconnected(token);
                }
                catch (Exception) { }
            }

            try
            {
                listenSocket?.Shutdown(SocketShutdown.Both);
            }
            catch (Exception) { }

            listenSocket?.Close();
            this.Active = false;

            clients.Clear();
        }
Пример #4
0
 void OnReceiveClientData(AsyncUserToken token, byte[] data)
 {
     messageQueue.Enqueue(new Message(token.connectionId, EventType.Data, data));
 }
Пример #5
0
        // This method is invoked when an asynchronous receive operation completes.
        // If the remote host closed the connection, then the socket is closed.
        protected override 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)
                {
                    ArraySegment <byte> data = new ArraySegment <byte>(e.Buffer, e.Offset, e.BytesTransferred);


                    // write it all into our memory stream first
                    token.buffer.Write(e.Buffer, e.Offset, e.BytesTransferred);

                    // keep trying headers (we might need to process >1 message)
                    while (token.buffer.Position >= 4)
                    {
                        // we can read a header. so read it.
                        long bufferSize = token.buffer.Position;
                        token.buffer.Position = 0;
                        byte[] header = new byte[4]; // TODO cache
                        token.buffer.Read(header, 0, header.Length);
                        int contentSize = Utils.BytesToIntBigEndian(header);

                        // avoid -1 attacks from hackers
                        if (contentSize > 0)
                        {
                            // enough content to finish the message?
                            if (bufferSize - token.buffer.Position >= contentSize)
                            {
                                // read content
                                byte[] content = new byte[contentSize];
                                token.buffer.Read(content, 0, content.Length);

                                // process message
                                OnReceiveClientData(token, content);

                                // read what's left in the buffer. this is valid
                                // data that we received at some point. can't lose
                                // it.
                                byte[] remainder = new byte[bufferSize - token.buffer.Position];
                                token.buffer.Read(remainder, 0, remainder.Length);

                                // write it to the beginning of the buffer. this
                                // sets position to the new true end automatically.
                                token.buffer.Position = 0;
                                token.buffer.Write(remainder, 0, remainder.Length);
                            }
                            // otherwise we just need to receive more.
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            CloseClientSocket(e);
                            Debug.LogWarning("Server.ProcessReceive: received negative contentSize: " + contentSize + ". Maybe an attacker tries to exploit the server?");
                        }
                    }


                    // continue receiving
                    if (!token.Socket.ReceiveAsync(e))
                    {
                        ProcessReceive(e);
                    }
                }
                else
                {
                    CloseClientSocket(e);
                }
            }
            catch (Exception exception)
            {
                CloseClientSocket(e);
                Debug.LogError("Server.ProcessReceive failed: " + exception);
            }
        }
Пример #6
0
 void OnClientDisconnected(AsyncUserToken token)
 {
     messageQueue.Enqueue(new Message(token.connectionId, EventType.Disconnected, null));
 }