/// <summary>
/// IP-aдрес сервреа по-умолчанию
/// Очевидный localhost
/// </summary>
private static IPAddress _defaultIPAddress = IPAddress.Parse("127.0.0.1");
/// <summary>
/// Порт сервера по-умлочанию
/// </summary>
private static int _defaultPort = 9000;
/// <summary>
/// Конечная точка сервреа по-умлочанию
/// </summary>
private static IPEndPoint _defaultEndPoint = new IPEndPoint(_defaultIPAddress, _defaultPort);
#endregion Default
#region Private vars
private TcpListener _listener = null;
private bool _isStoped = false;
private bool _isPurgingStoped = false;
private Task _listeningTask = null;
private Task _purgingTask = null;
private ConcurrentDictionary<Guid, TcpSession<T>> _sessions = null;//сессии сервера
private object locker = new object(); //объект синхронизации потоков
private DateTime _startTime;
private CancellationToken cancellationToken;
#endregion Private vars
#region Props
public int ConnectedSessionCount => this._sessions.Where(kv => !kv.Value.IsStoped).Count();
public TimeSpan UpTime => DateTime.Now - _startTime;
public bool IsRuning => !_isStoped;
#endregion Props
#region ctors
public TcpServer() : this(_defaultEndPoint)
{
}
public TcpServer(int port) : this(new IPEndPoint(_defaultIPAddress, port))
{
}
public TcpServer(IPAddress address) : this(new IPEndPoint(address, _defaultPort))
{
}
public TcpServer(IPAddress address, int port) : this(new IPEndPoint(address, port))
{
}
public TcpServer(IPEndPoint endPoint)
{
Init(endPoint);
}
#endregion ctors
#region Public methods
public void Start(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
if(_listener != null)
{
_startTime = DateTime.Now;
_sessions = new ConcurrentDictionary<Guid, TcpSession<T>>();
_listener.Start();
_listeningTask = new Task(ServerListeningTask);
_listeningTask.Start();
//Создаем nfcr очистки сессий
_purgingTask = new Task(ServerPurgingTask);
_purgingTask.Start();
}
}
public void Stop()
{
if(_listener != null || cancellationToken.IsCancellationRequested)
{
try
{
_isStoped = true;
_listener.Stop();
_listeningTask.Wait();
_listeningTask = null;
_purgingTask.Wait();
_purgingTask = null;
_listener = null;
StopAllClientSessions();
}
catch
{
}
}
}
#endregion Public methods
#region Private methods
private void Init(IPEndPoint endPoint)
{
try
{
_listener = new TcpListener(endPoint);
}
catch(Exception ex)
{
_listener = null;
}
}
private void ServerListeningTask()
{
Socket clientSocket = null;
TcpSession<T> clientSession = null;
while(!_isStoped || !this.cancellationToken.IsCancellationRequested)
{
try
{
clientSocket = _listener.AcceptSocket();
clientSession = new TcpSession<T>(clientSocket);
lock(locker)
{
_sessions.TryAdd(clientSession.ID, clientSession);
}
clientSession.StartSession(this.cancellationToken);
}
catch(SocketException ex)
{
_isStoped = true;
}
}
}
private void ServerPurgingTask()
{
while(!_isPurgingStoped || !cancellationToken.IsCancellationRequested)
{
var disconnected = _sessions.Where(s => s.Value.IsStoped == true);
lock(locker)
{
foreach(var s in disconnected)
{
_sessions.TryRemove(s.Key, out var temp);
}
}
disconnected = null;
Thread.Sleep(1000);
}
}
private void StopAllClientSessions()
{
foreach(var kv in _sessions)
kv.Value.StopSession();
}
#endregion Private methods