using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace NNTCPApp.TCP.NNSocket { /// /// Creates a collection of TCP listners /// public class TCPListener { private TCPListener(NetworkItem host) { Host = host; } public static TCPListener Create(NetworkItem host) { if (!SocketListener.TryGetValue(host, out TCPListener listener)) SocketListener[host] = listener = new TCPListener(host); return listener; } private void OnAcceptCallback(object sender, SocketAsyncEventArgs e) { _eventStatus.Set(); Socket listenSocket = (Socket)sender; do { try { if (IsConnected && e.AcceptSocket.AddressFamily == AddressFamily.InterNetwork) { _connectedClients.Add(new ClientSocket(e.AcceptSocket)); _connectedClients.Last().Connect(_mesageReceived, ClientSocketClosed); } } catch { } finally { e.AcceptSocket = null; // to enable reuse } } while (listenSocket.IsConnected().Result && !listenSocket.AcceptAsync(e)); } #region "Methods" public void Disconnect() { IsConnected = false; foreach (ClientSocket socket in _connectedClients) socket.Dispose(); _connectedClients.Clear(); _listener?.Close(); _listener?.Dispose(); } public async void Connect(Action action) { IsConnected = true; IPEndPoint localEndPoint = new IPEndPoint(Host.NetworkIP, Host.Port); _mesageReceived = action; await Task.Factory.StartNew(() => StartListning(localEndPoint)); _mesageReceived("Disconnected"); IsConnected = false; } public void SendMessage(string message) { foreach (ClientSocket item in _connectedClients) item.Send(message); } private void ClientSocketClosed(ClientSocket sender) { if (_connectedClients.Contains(sender)) { _connectedClients.Remove(sender); sender.Stop(); } } private void StartListning(IPEndPoint localEndPoint) { // Create a TCP/IP socket. using (_listener = new Socket(Host.NetworkIP.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { _mesageReceived("listening"); // Bind the socket to the local endpoint and // listen for incoming connections. try { _listener.Bind(localEndPoint); _listener.Listen(100); SocketAsyncEventArgs e = new SocketAsyncEventArgs(); e.Completed += OnAcceptCallback; if (!_listener.AcceptAsync(e)) { OnAcceptCallback(_listener, e); } while (IsConnected) { _eventStatus.Reset(); _eventStatus.WaitOne(); } e.Completed -= OnAcceptCallback; } catch (Exception ex) { _mesageReceived(ex.Message); } } } #endregion #region "Properties" public NetworkItem Host { get; } public bool IsConnected { get; private set; } private static Dictionary SocketListener { get; } = new Dictionary(); #endregion #region "Fields" private Socket _listener; private Action _mesageReceived; private static ManualResetEvent _eventStatus = new ManualResetEvent(false); private List _connectedClients = new List(); #endregion } }