using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; namespace Syroot.Worms.Mgame.GameServer { /// /// Represents a server listening for incoming client connections and dispatching them into /// instances. /// internal class Server { // ---- FIELDS ------------------------------------------------------------------------------------------------- private readonly List _clients = new List(); // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ internal Server() { // Create and read the configuration. Config = new ConfigurationBuilder() .AddJsonFile("ServerConfig.json", true) .Build() .Get(); } // ---- PROPERTIES --------------------------------------------------------------------------------------------- internal Config Config { get; } internal Log Log { get; } = new Log(); // ---- METHODS (INTERNAL) ------------------------------------------------------------------------------------- /// /// Starts the server by accepting new client connections under the given and /// dispatching them into asynchronous handling threads. This call is blocking. /// /// The port on which to listen for new client connections. internal void Listen() { TcpListener tcpListener = new TcpListener(IPAddress.Any, Config.Port); tcpListener.Start(); Log.Write(LogCategory.Server, $"Listening on {Config.EndPoint}..."); while (true) { // Continually accept clients. TcpClient tcpClient = tcpListener.AcceptTcpClient(); Log.Write(LogCategory.Connect, $"{tcpClient.Client.RemoteEndPoint} connected"); Client client = new Client(tcpClient, this); _clients.Add(client); // Dispatch the client into its listening thread and remove it when listening aborts. Task.Run(client.Listen).ContinueWith(_ => { Log.Write(LogCategory.Disconnect, $"{client.TcpClient.Client.RemoteEndPoint} disconnected"); _clients.Remove(client); client.Dispose(); }); } } } }