[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/etheaven/NETCoreServer/master/source/NETCoreServer/TcpServer.cs [Back]  [Original]

using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace NETCoreServer
{
    /// 
    /// TCP server is used to connect, disconnect and manage TCP sessions
    /// 
    public class TcpServer
    {
        /// 
        /// Initialize TCP server with a given IP address and port number
        /// 
        /// IP address
        /// Port number
        public TcpServer(IPAddress address, int port) : this(new IPEndPoint(address, port)) {}

        /// 
        /// Initialize TCP server with a given IP address and port number
        /// 
        /// IP address
        /// Port number
        public TcpServer(string address, int port) : this(new IPEndPoint(IPAddress.Parse(address), port)) {}

        /// 
        /// Initialize TCP server with a given IP endpoint
        /// 
        /// IP endpoint
        public TcpServer(IPEndPoint endpoint) { Endpoint = endpoint; }

        /// 
        /// IP endpoint
        /// 
        public IPEndPoint Endpoint { get; internal set; }

        /// 
        /// Number of sessions connected to the server
        /// 
        public long ConnectedSessions { get; internal set; }
        /// 
        /// Number of bytes pending sent by the server
        /// 
        public long BytesPending { get; internal set; }
        /// 
        /// Number of bytes sent by the server
        /// 
        public long BytesSent { get; internal set; }
        /// 
        /// Number of bytes received by the server
        /// 
        public long BytesReceived { get; internal set; }

        /// 
        /// Option: keep alive
        /// 
        /// 
        /// This option will setup SO_KEEPALIVE if the OS support this feature
        /// 
        public bool OptionKeepAlive { get; set; }
        /// 
        /// Option: no delay
        /// 
        /// 
        /// This option will enable/disable Nagle's algorithm for TCP protocol
        /// 
        public bool OptionNoDelay { get; set; }
        /// 
        /// Option: reuse address
        /// 
        /// 
        /// This option will enable/disable SO_REUSEADDR if the OS support this feature
        /// 
        public bool OptionReuseAddress { get; set; }
        /// 
        /// Option: reuse port
        /// 
        /// 
        /// This option will enable/disable SO_REUSEPORT if the OS support this feature
        /// 
        public bool OptionReusePort { get; set; }

        #region Start/Stop server

        private int _acceptorBacklog = 1024;
        private Socket _acceptorSocket;
        private SocketAsyncEventArgs _acceptorEventArg;

        /// 
        /// Is the server started?
        /// 
        public bool IsStarted { get; private set; }
        /// 
        /// Is the server accepting new clients?
        /// 
        public bool IsAccepting { get; private set; }

        /// 
        /// Start the server
        /// 
        /// 'true' if the server was successfully started, 'false' if the server failed to start
        public bool Start()
        {
            Debug.Assert(!IsStarted, "TCP server is already started!");
            if (IsStarted)
                return false;

            // Create a new acceptor socket
            _acceptorSocket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            // Bind the acceptor socket to the IP endpoint
            _acceptorSocket.Bind(Endpoint);
            // Start listen to the acceptor socket with the given accepting backlog size
            _acceptorSocket.Listen(_acceptorBacklog);

            // Reset statistic
            BytesPending = 0;
            BytesSent = 0;
            BytesReceived = 0;

            // Update the started flag
            IsStarted = true;

            // Call the server started handler
            OnStarted();

            // Perform the first server accept
            IsAccepting = true;
            _acceptorEventArg = new SocketAsyncEventArgs();
            _acceptorEventArg.Completed += AcceptorEventArg_Completed;
            StartAccept(_acceptorEventArg);

            return true;
        }

        /// 
        /// Stop the server
        /// 
        /// 'true' if the server was successfully stopped, 'false' if the server is already stopped
        public bool Stop()
        {
            Debug.Assert(IsStarted, "TCP server is not started!");
            if (!IsStarted)
                return false;

            // Stop accepting new clients
            IsAccepting = false;

            // Close the acceptor socket
            _acceptorSocket.Close();

            // Disconnect all sessions
            DisconnectAll();

            // Update the started flag
            IsStarted = false;

            // Clear multicast buffer
            ClearBuffers();

            // Call the server stopped handler
            OnStopped();

            return true;
        }

        /// 
        /// Restart the server
        /// 
        /// 'true' if the server was successfully restarted, 'false' if the server failed to restart
        public bool Restart()
        {
            if (!Stop())
                return false;

            while (IsStarted)
                Thread.Yield();

            return Start();
        }

        /// 
        /// Handle server started notification
        /// 
        protected virtual void OnStarted() {}
        /// 
        /// Handle server stopped notification
        /// 
        protected virtual void OnStopped() {}

        /// 
        /// Handle error notification
        /// 
        /// Socket error code
        protected virtual void OnError(SocketError error) {}

        #endregion

        #region Accepting clients

        /// 
        /// Start accept a new client connection
        /// 
        private void StartAccept(SocketAsyncEventArgs e)
        {
            // Socket must be cleared since the context object is being reused
            e.AcceptSocket = null;

            if (!_acceptorSocket.AcceptAsync(e))
                ProcessAccept(e);
        }

        /// 
        /// Process accepted client connection
        /// 
        private void ProcessAccept(SocketAsyncEventArgs e)
        {


            // Accept the next client connection
            if (IsAccepting)
                StartAccept(e);
        }

        /// 
        /// This method is the callback method associated with Socket.AcceptAsync()
        /// operations and is invoked when an accept operation is complete
        /// 
        private void AcceptorEventArg_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        #endregion

        #region Multicasting

        /// 
        /// Clear multicast buffer
        /// 
        private void ClearBuffers()
        {

        }

        #endregion

        #region Session management

        /// 
        /// Disconnect all connected sessions
        /// 
        /// 'true' if all sessions were successfully disconnected, 'false' if the server is not started
        public bool DisconnectAll()
        {
            return true;
        }

        #endregion
    }
}

Web Proxy Viewer  |  New URL  |  Original Page