using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.Logging; namespace Tango.Transport.Servers { /// /// Represents a TCP/IP listener wrapper. /// public class TcpServer { private LogManager LogManager = LogManager.Default; /// /// The TcpListener that is encapsulated behind this Server instance. /// public TcpListener Listener { get; set; } /// /// The Port that is used to listen to incoming connections. /// public int Port { get; set; } /// /// Returns true if the Server instance is running. /// public bool IsStarted { get; private set; } #region Events public event EventHandler ClientConnected; #endregion #region Constructors /// /// Initializes a new Server instance. /// /// The port number that is used to listen for incoming connections. public TcpServer(int port) { Port = port; } #endregion #region Public Methods /// /// Start Listening for incoming connections. /// public void Start() { if (!IsStarted) { Listener = new TcpListener(System.Net.IPAddress.Any, Port); Listener.ExclusiveAddressUse = false; Listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); Listener.Start(); IsStarted = true; LogManager.Log($"TCP server started on port {Port}."); WaitForConnection(); } } /// /// Stop listening for incoming connections. /// public void Stop() { if (IsStarted) { Listener.Stop(); IsStarted = false; LogManager.Log($"TCP server stopped on port {Port}."); } } #endregion #region Incoming Connections Methods private void WaitForConnection() { Listener.BeginAcceptTcpClient(new AsyncCallback(ConnectionHandler), null); } private void ConnectionHandler(IAsyncResult ar) { if (IsStarted) { try { OnClientConnected(Listener.EndAcceptTcpClient(ar)); WaitForConnection(); } #pragma warning disable CS0168 // Variable is declared but never used catch (ObjectDisposedException ex) #pragma warning restore CS0168 // Variable is declared but never used { //Ignore.. } } } #endregion #region Virtual Methods protected virtual void OnClientConnected(TcpClient socket) { ClientConnected?.Invoke(this, new ClientConnectedEventArgs(socket)); } #endregion } }