/// <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
CQkvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIElQLWHQtNGA0LXRgSDRgdC10YDQstGA0LXQsCDQv9C+LdGD0LzQvtC70YfQsNC90LjRjgogICAgICAgIC8vLyDQntGH0LXQstC40LTQvdGL0LkgbG9jYWxob3N0CiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICBwcml2YXRlIHN0YXRpYyBJUEFkZHJlc3MgX2RlZmF1bHRJUEFkZHJlc3MgPSBJUEFkZHJlc3MuUGFyc2UoIjEyNy4wLjAuMSIpOwoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vINCf0L7RgNGCINGB0LXRgNCy0LXRgNCwINC/0L4t0YPQvNC70L7Rh9Cw0L3QuNGOCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICBwcml2YXRlIHN0YXRpYyBpbnQgX2RlZmF1bHRQb3J0ID0gOTAwMDsKCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyDQmtC+0L3QtdGH0L3QsNGPINGC0L7Rh9C60LAg0YHQtdGA0LLRgNC10LAg0L/Qvi3Rg9C80LvQvtGH0LDQvdC40Y4KICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIHByaXZhdGUgc3RhdGljIElQRW5kUG9pbnQgX2RlZmF1bHRFbmRQb2ludCA9IG5ldyBJUEVuZFBvaW50KF9kZWZhdWx0SVBBZGRyZXNzLCBfZGVmYXVsdFBvcnQpOwoKICAgICAgICAjZW5kcmVnaW9uIERlZmF1bHQKCiAgICAgICAgI3JlZ2lvbiBQcml2YXRlIHZhcnMKCiAgICAgICAgcHJpdmF0ZSBUY3BMaXN0ZW5lciBfbGlzdGVuZXIgPSBudWxsOwogICAgICAgIHByaXZhdGUgYm9vbCBfaXNTdG9wZWQgPSBmYWxzZTsKICAgICAgICBwcml2YXRlIGJvb2wgX2lzUHVyZ2luZ1N0b3BlZCA9IGZhbHNlOwogICAgICAgIHByaXZhdGUgVGFzayBfbGlzdGVuaW5nVGFzayA9IG51bGw7CiAgICAgICAgcHJpdmF0ZSBUYXNrIF9wdXJnaW5nVGFzayA9IG51bGw7CiAgICAgICAgcHJpdmF0ZSBDb25jdXJyZW50RGljdGlvbmFyeTxHdWlkLCBUY3BTZXNzaW9uPFQ+PiBfc2Vzc2lvbnMgPSBudWxsOy8v0YHQtdGB0YHQuNC4INGB0LXRgNCy0LXRgNCwCiAgICAgICAgcHJpdmF0ZSBvYmplY3QgbG9ja2VyID0gbmV3IG9iamVjdCgpOyAvL9C+0LHRitC10LrRgiDRgdC40L3RhdGA0L7QvdC40LfQsNGG0LjQuCDQv9C+0YLQvtC60L7QsgogICAgICAgIHByaXZhdGUgRGF0ZVRpbWUgX3N0YXJ0VGltZTsKICAgICAgICBwcml2YXRlIENhbmNlbGxhdGlvblRva2VuIGNhbmNlbGxhdGlvblRva2VuOwoKICAgICAgICAjZW5kcmVnaW9uIFByaXZhdGUgdmFycwoKICAgICAgICAjcmVnaW9uIFByb3BzCgogICAgICAgIHB1YmxpYyBpbnQgQ29ubmVjdGVkU2Vzc2lvbkNvdW50ID0+IHRoaXMuX3Nlc3Npb25zLldoZXJlKGt2ID0+ICFrdi5WYWx1ZS5Jc1N0b3BlZCkuQ291bnQoKTsKICAgICAgICBwdWJsaWMgVGltZVNwYW4gVXBUaW1lID0+IERhdGVUaW1lLk5vdyAtIF9zdGFydFRpbWU7CiAgICAgICAgcHVibGljIGJvb2wgSXNSdW5pbmcgPT4gIV9pc1N0b3BlZDsKCiAgICAgICAgI2VuZHJlZ2lvbiBQcm9wcwoKICAgICAgICAjcmVnaW9uIGN0b3JzCgogICAgICAgIHB1YmxpYyBUY3BTZXJ2ZXIoKSA6IHRoaXMoX2RlZmF1bHRFbmRQb2ludCkKICAgICAgICB7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgVGNwU2VydmVyKGludCBwb3J0KSA6IHRoaXMobmV3IElQRW5kUG9pbnQoX2RlZmF1bHRJUEFkZHJlc3MsIHBvcnQpKQogICAgICAgIHsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBUY3BTZXJ2ZXIoSVBBZGRyZXNzIGFkZHJlc3MpIDogdGhpcyhuZXcgSVBFbmRQb2ludChhZGRyZXNzLCBfZGVmYXVsdFBvcnQpKQogICAgICAgIHsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBUY3BTZXJ2ZXIoSVBBZGRyZXNzIGFkZHJlc3MsIGludCBwb3J0KSA6IHRoaXMobmV3IElQRW5kUG9pbnQoYWRkcmVzcywgcG9ydCkpCiAgICAgICAgewogICAgICAgIH0KCiAgICAgICAgcHVibGljIFRjcFNlcnZlcihJUEVuZFBvaW50IGVuZFBvaW50KQogICAgICAgIHsKICAgICAgICAgICAgSW5pdChlbmRQb2ludCk7CiAgICAgICAgfQoKICAgICAgICAjZW5kcmVnaW9uIGN0b3JzCgogICAgICAgICNyZWdpb24gUHVibGljIG1ldGhvZHMKCiAgICAgICAgcHVibGljIHZvaWQgU3RhcnQoQ2FuY2VsbGF0aW9uVG9rZW4gY2FuY2VsbGF0aW9uVG9rZW4pCiAgICAgICAgewogICAgICAgICAgICB0aGlzLmNhbmNlbGxhdGlvblRva2VuID0gY2FuY2VsbGF0aW9uVG9rZW47CiAgICAgICAgICAgIGlmKF9saXN0ZW5lciAhPSBudWxsKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBfc3RhcnRUaW1lID0gRGF0ZVRpbWUuTm93OwogICAgICAgICAgICAgICAgX3Nlc3Npb25zID0gbmV3IENvbmN1cnJlbnREaWN0aW9uYXJ5PEd1aWQsIFRjcFNlc3Npb248VD4+KCk7CiAgICAgICAgICAgICAgICBfbGlzdGVuZXIuU3RhcnQoKTsKCiAgICAgICAgICAgICAgICBfbGlzdGVuaW5nVGFzayA9IG5ldyBUYXNrKFNlcnZlckxpc3RlbmluZ1Rhc2spOwogICAgICAgICAgICAgICAgX2xpc3RlbmluZ1Rhc2suU3RhcnQoKTsKCiAgICAgICAgICAgICAgICAvL9Ch0L7Qt9C00LDQtdC8IG5mY3Ig0L7Rh9C40YHRgtC60Lgg0YHQtdGB0YHQuNC5CiAgICAgICAgICAgICAgICBfcHVyZ2luZ1Rhc2sgPSBuZXcgVGFzayhTZXJ2ZXJQdXJnaW5nVGFzayk7CiAgICAgICAgICAgICAgICBfcHVyZ2luZ1Rhc2suU3RhcnQoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcHVibGljIHZvaWQgU3RvcCgpCiAgICAgICAgewogICAgICAgICAgICBpZihfbGlzdGVuZXIgIT0gbnVsbCB8fCBjYW5jZWxsYXRpb25Ub2tlbi5Jc0NhbmNlbGxhdGlvblJlcXVlc3RlZCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgdHJ5CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgX2lzU3RvcGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBfbGlzdGVuZXIuU3RvcCgpOwogICAgICAgICAgICAgICAgICAgIF9saXN0ZW5pbmdUYXNrLldhaXQoKTsKICAgICAgICAgICAgICAgICAgICBfbGlzdGVuaW5nVGFzayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgX3B1cmdpbmdUYXNrLldhaXQoKTsKICAgICAgICAgICAgICAgICAgICBfcHVyZ2luZ1Rhc2sgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIF9saXN0ZW5lciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgU3RvcEFsbENsaWVudFNlc3Npb25zKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjYXRjaAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAjZW5kcmVnaW9uIFB1YmxpYyBtZXRob2RzCgogICAgICAgICNyZWdpb24gUHJpdmF0ZSBtZXRob2RzCgogICAgICAgIHByaXZhdGUgdm9pZCBJbml0KElQRW5kUG9pbnQgZW5kUG9pbnQpCiAgICAgICAgewogICAgICAgICAgICB0cnkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgX2xpc3RlbmVyID0gbmV3IFRjcExpc3RlbmVyKGVuZFBvaW50KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaChFeGNlcHRpb24gZXgpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIF9saXN0ZW5lciA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHByaXZhdGUgdm9pZCBTZXJ2ZXJMaXN0ZW5pbmdUYXNrKCkKICAgICAgICB7CiAgICAgICAgICAgIFNvY2tldCBjbGllbnRTb2NrZXQgPSBudWxsOwogICAgICAgICAgICBUY3BTZXNzaW9uPFQ+IGNsaWVudFNlc3Npb24gPSBudWxsOwogICAgICAgICAgICB3aGlsZSghX2lzU3RvcGVkIHx8ICF0aGlzLmNhbmNlbGxhdGlvblRva2VuLklzQ2FuY2VsbGF0aW9uUmVxdWVzdGVkKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB0cnkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjbGllbnRTb2NrZXQgPSBfbGlzdGVuZXIuQWNjZXB0U29ja2V0KCk7CiAgICAgICAgICAgICAgICAgICAgY2xpZW50U2Vzc2lvbiA9IG5ldyBUY3BTZXNzaW9uPFQ+KGNsaWVudFNvY2tldCk7CiAgICAgICAgICAgICAgICAgICAgbG9jayhsb2NrZXIpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBfc2Vzc2lvbnMuVHJ5QWRkKGNsaWVudFNlc3Npb24uSUQsIGNsaWVudFNlc3Npb24pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjbGllbnRTZXNzaW9uLlN0YXJ0U2Vzc2lvbih0aGlzLmNhbmNlbGxhdGlvblRva2VuKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNhdGNoKFNvY2tldEV4Y2VwdGlvbiBleCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBfaXNTdG9wZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgU2VydmVyUHVyZ2luZ1Rhc2soKQogICAgICAgIHsKICAgICAgICAgICAgd2hpbGUoIV9pc1B1cmdpbmdTdG9wZWQgfHwgIWNhbmNlbGxhdGlvblRva2VuLklzQ2FuY2VsbGF0aW9uUmVxdWVzdGVkKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB2YXIgZGlzY29ubmVjdGVkID0gX3Nlc3Npb25zLldoZXJlKHMgPT4gcy5WYWx1ZS5Jc1N0b3BlZCA9PSB0cnVlKTsKICAgICAgICAgICAgICAgIGxvY2sobG9ja2VyKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGZvcmVhY2godmFyIHMgaW4gZGlzY29ubmVjdGVkKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgX3Nlc3Npb25zLlRyeVJlbW92ZShzLktleSwgb3V0IHZhciB0ZW1wKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBkaXNjb25uZWN0ZWQgPSBudWxsOwogICAgICAgICAgICAgICAgVGhyZWFkLlNsZWVwKDEwMDApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIHZvaWQgU3RvcEFsbENsaWVudFNlc3Npb25zKCkKICAgICAgICB7CiAgICAgICAgICAgIGZvcmVhY2godmFyIGt2IGluIF9zZXNzaW9ucykKICAgICAgICAgICAgICAgIGt2LlZhbHVlLlN0b3BTZXNzaW9uKCk7CiAgICAgICAgfQoKICAgICAgICAjZW5kcmVnaW9uIFByaXZhdGUgbWV0aG9kcwo=
prog.cs(5,23): error CS1525: Unexpected symbol `IPAddress', expecting `class', `delegate', `enum', `interface', `partial', `ref', or `struct'
prog.cs(18,0): error CS1028: Unexpected processor directive (no #region for this #endregion)
Compilation failed: 2 error(s), 0 warnings