using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using DFEngine.Logging; namespace DFEngine.Network { /// /// Class that listens for incoming network connections using the /// TCP socket protocol. /// public class NetworkServer : Object { /// /// The default backlog size, which will be used if none is provided. /// public const int BacklogSize = 100; /// /// A list of the active connections to the . /// public List Connections { get; } /// /// Returns true if this server listens for local (server-to-server) connections. /// public bool IsInterService => _connectionType != NetworkConnectionType.NCT_CLIENT; /// /// The type of connections the server is listening for. /// private readonly NetworkConnectionType _connectionType; /// /// The socket that listens for connections. /// private readonly Socket _socket; /// /// Creates a new instance of the class. /// public NetworkServer(NetworkConnectionType connectionType) { Connections = new List(); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._connectionType = connectionType; } /// /// Places the server in the listening state. /// /// The IP address to listen for connection on. /// The port to listen for connections on. /// The maximum number of pending connections in the queue. public void Listen(string ipAddress, ushort port, int backlog = BacklogSize) { if (!IPAddress.TryParse(ipAddress, out var address)) { SocketLog.Write(SocketLogLevel.Exception, $"The IPAddress {ipAddress} is invalid."); return; } _socket.Bind(new IPEndPoint(address, port)); _socket.Listen(backlog); _socket.BeginAccept(AcceptConnection, _socket); } /// /// Accepts a pending connection. /// /// The status of the operation. private void AcceptConnection(IAsyncResult e) { if (e.AsyncState == null) { SocketLog.Write(SocketLogLevel.Exception, "NetworkServer::AcceptConnection : AsyncState is null"); return; } var serverSocket = (Socket)e.AsyncState; var clientSocket = serverSocket.EndAccept(e); if (clientSocket != null) { var connection = new NetworkConnection(this, clientSocket, _connectionType); if (connection.IsConnected) { Connections.Add(connection); } } // Begin accepting connections again. serverSocket.BeginAccept(AcceptConnection, serverSocket); } /// /// Destroys the instance. /// protected override void Destroy() { // Close() calls the dispose method for us. _socket.Close(); } } }