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
}
}