using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; namespace IgniteEngine.Networking { /// /// 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 BACKLOG_SIZE = 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 = BACKLOG_SIZE) { if (!IPAddress.TryParse(ipAddress, out var address)) { Debug.LogAssert($"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) { Debug.LogAssert("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(); } } }