/// <summary>
        /// Releases the Stream's SocketAsyncEventArgs back to the pool,
        /// and free's up another slot for a new client to connect
        /// </summary>
        /// <param name="Stream">The GamespyTcpStream object that is being released.</param>
        public void Release(GamespyTcpStream Stream)
        {
            // If the stream has been released, then we stop here
            if (!IsListening || Stream.Released)
            {
                return;
            }

            // Make sure the connection is closed properly
            if (!Stream.SocketClosed)
            {
                Stream.Close();
                return;
            }

            // To prevent cross instance releasing
            if (!Object.ReferenceEquals(this, Stream.SocketManager))
            {
                throw new ArgumentException("Cannot pass a GamespyTcpStream belonging to a different TcpSocket than this one.");
            }

            // If we are still registered for this event, then the EventArgs should
            // NEVER be disposed here, or we have an error to fix
            if (Stream.DisposedEventArgs)
            {
                // Log this error
                Program.ErrorLog.Write("WARNING: [GamespyTcpSocket.Release] Event Args were disposed imporperly!");

                // Dispose old buffer tokens
                BufferManager.ReleaseBuffer(Stream.ReadEventArgs);
                BufferManager.ReleaseBuffer(Stream.WriteEventArgs);

                // Create new Read Event Args
                SocketAsyncEventArgs SockArgR = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArgR);
                SocketReadWritePool.Push(SockArgR);

                // Create new Write Event Args
                SocketAsyncEventArgs SockArgW = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArgW);
                SocketReadWritePool.Push(SockArgW);
            }
            else
            {
                // Set null's
                Stream.ReadEventArgs.AcceptSocket  = null;
                Stream.WriteEventArgs.AcceptSocket = null;

                // Get our ReadWrite AsyncEvent object back
                SocketReadWritePool.Push(Stream.ReadEventArgs);
                SocketReadWritePool.Push(Stream.WriteEventArgs);
            }

            // Now that we have another set of AsyncEventArgs, we can
            // release this users Semephore lock, allowing another connection
            MaxConnectionsEnforcer.Release();
        }
Beispiel #2
0
        /// <summary>
        /// Creates a new UDP socket for handling Gamespy Protocol
        /// </summary>
        /// <param name="Port">The port this socket will be bound to</param>
        /// <param name="MaxConnections">The maximum number of concurrent connections</param>
        public GamespyUdpSocket(int Port, int MaxConnections)
        {
            // Create our Socket
            this.Port = Port;
            Listener  = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
            {
                SendTimeout       = 5000, // We have a limited pool, so we dont want to be locked often
                SendBufferSize    = BufferSizePerEvent,
                ReceiveBufferSize = BufferSizePerEvent
            };

            // Bind to our port
            Listener.Bind(new IPEndPoint(IPAddress.Any, Port));

            // Set the rest of our internals
            MaxNumConnections      = MaxConnections;
            MaxConnectionsEnforcer = new SemaphoreSlim(MaxNumConnections, MaxNumConnections);
            SocketReadWritePool    = new SocketAsyncEventArgsPool(MaxNumConnections);

            // Create our Buffer Manager for IO operations.
            BufferManager = new BufferManager(MaxNumConnections, BufferSizePerEvent);

            // Assign our Connection IO SocketAsyncEventArgs object instances
            for (int i = 0; i < MaxNumConnections; i++)
            {
                SocketAsyncEventArgs SockArg = new SocketAsyncEventArgs();
                SockArg.Completed += IOComplete;
                BufferManager.AssignBuffer(SockArg);
                SocketReadWritePool.Push(SockArg);
            }

            // set public internals
            IsRunning  = true;
            IsDisposed = false;
        }
        /// <summary>
        /// Creates a new TCP socket for handling Gamespy Protocol
        /// </summary>
        /// <param name="Port">The port this socket will be bound to</param>
        /// <param name="MaxConnections">The maximum number of concurrent connections</param>
        public GamespyTcpSocket(int Port, int MaxConnections)
        {
            // Create our Socket
            Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Set Socket options
            Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, false);
            Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

            // Bind to our port
            Listener.Bind(new IPEndPoint(IPAddress.Any, Port));
            Listener.Listen(25);

            // Set the rest of our internals
            MaxNumConnections      = MaxConnections;
            MaxConnectionsEnforcer = new SemaphoreSlim(MaxNumConnections, MaxNumConnections);
            SocketAcceptPool       = new SocketAsyncEventArgsPool(ConcurrentAcceptPoolSize);
            SocketReadWritePool    = new SocketAsyncEventArgsPool(MaxNumConnections);

            // Create our Buffer Manager for IO operations.
            // Always allocate double space, one for recieving, and another for sending
            BufferManager = new BufferManager(MaxNumConnections * 2, BufferSizePerEventArg);

            // Assign our Connection Accept SocketAsyncEventArgs object instances
            for (int i = 0; i < ConcurrentAcceptPoolSize; i++)
            {
                SocketAsyncEventArgs SockArg = new SocketAsyncEventArgs();
                SockArg.Completed += (s, e) => PrepareAccept(e);

                // Do NOT assign buffer space for Accept operations!
                // AcceptAsync does not take require a parameter for buffer size.
                SocketAcceptPool.Push(SockArg);
            }

            // Assign our Connection IO SocketAsyncEventArgs object instances
            for (int i = 0; i < MaxNumConnections * 2; i++)
            {
                SocketAsyncEventArgs SockArg = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArg);
                SocketReadWritePool.Push(SockArg);
            }

            // set public internals
            IsListening          = true;
            IgnoreNewConnections = false;
            IsDisposed           = false;
        }
Beispiel #4
0
        public TCPServer(string serverName, IPEndPoint bindTo, int MaxConnections)
        {
            ServerName = "[" + serverName + "]";
            // Create our Socket
            Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // Set Socket options
            Listener.LingerState = new LingerOption(enable: false, seconds: 0);
            Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

            // Bind to our port
            Listener.Bind(bindTo);
            Listener.Listen(25);

            // Set the rest of our internals
            MaxNumConnections      = MaxConnections;
            MaxConnectionsEnforcer = new SemaphoreSlim(MaxNumConnections, MaxNumConnections);
            SocketAcceptPool       = new SocketAsyncEventArgsPool(ConcurrentAcceptPoolSize);
            SocketReadWritePool    = new SocketAsyncEventArgsPool(MaxNumConnections * 2);

            // Create our Buffer Manager for IO operations.
            // Always allocate double space, one for recieving, and another for sending
            BufferManager = new BufferManager(MaxNumConnections * 2, BufferSizePerOperation);

            // Assign our Connection Accept SocketAsyncEventArgs object instances
            for (int i = 0; i < ConcurrentAcceptPoolSize; i++)
            {
                SocketAsyncEventArgs SockArg = new SocketAsyncEventArgs();
                SockArg.Completed += (s, e) => PrepareAccept(e);

                // Do NOT assign buffer space for Accept operations!
                SocketAcceptPool.Push(SockArg);
            }

            // Assign our Connection IO SocketAsyncEventArgs object instances
            for (int i = 0; i < MaxNumConnections * 2; i++)
            {
                SocketAsyncEventArgs SockArg = new SocketAsyncEventArgs();
                BufferManager.AssignBuffer(SockArg);
                SocketReadWritePool.Push(SockArg);
            }

            // set public internals
            IsListening = true;
        }