fork download
  1. using Microsoft.Extensions.Logging;
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Linq;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8.  
  9. namespace Shared.TCP
  10. {
  11. public class TcpServer
  12. {
  13. private readonly ILogger<TcpServer> _logger;
  14. private readonly IServerConfiguration _serverConfiguration;
  15.  
  16. private readonly ConcurrentDictionary<Guid, Socket> _clients = new ConcurrentDictionary<Guid, Socket>();
  17.  
  18. private object _startLocker = new object();
  19. private bool _isStarted;
  20.  
  21. public TcpServer(ILogger<TcpServer> logger, IServerConfiguration serverConfiguration)
  22. {
  23. if (logger is null)
  24. {
  25. throw new ArgumentNullException(nameof(logger));
  26. }
  27.  
  28. if (serverConfiguration is null)
  29. {
  30. throw new ArgumentNullException(nameof(serverConfiguration));
  31. }
  32. _logger = logger;
  33. _serverConfiguration = serverConfiguration;
  34. }
  35.  
  36. public async Task StartAsync(CancellationToken cancellationToken)
  37. {
  38. lock (_startLocker)
  39. {
  40. if (_isStarted)
  41. {
  42. _logger.LogWarning("Server alrady started");
  43. return;
  44. }
  45. _isStarted = true;
  46. }
  47. Thread handleConnected = new Thread(async () =>
  48. {
  49. try
  50. {
  51.  
  52. while (!cancellationToken.IsCancellationRequested)
  53. {
  54. //Проверим на связи ли клиент пинганув
  55.  
  56.  
  57. foreach(var c in _clients)
  58. {
  59. try
  60. {
  61. await SendToClient(c.Key, Array.Empty<byte>());
  62.  
  63. }
  64. catch(Exception ex)
  65. {
  66. _logger.LogError(ex.ToString());
  67. }
  68. }
  69.  
  70. //Чистим отвалившихся
  71. var disconnected = _clients.Where(x => x.Value.Connected);
  72. foreach (var it in disconnected)
  73. {
  74. var removed = _clients.TryRemove(it.Key, out var client);
  75. if (!removed)
  76. {
  77. _logger.LogWarning($"Cant remove disconnected client with GUID {it.Key}");
  78. continue;
  79. }
  80. client.Shutdown(SocketShutdown.Both);
  81. client.Close();
  82. }
  83. await Task.Delay(1000, cancellationToken);
  84. }
  85. }
  86. catch (Exception ex)
  87. {
  88. _logger.LogDebug(ex.ToString());
  89. }
  90. });
  91.  
  92. Thread acceptClientThread = new Thread(
  93. async () =>
  94. {
  95. try
  96. {
  97. cancellationToken.ThrowIfCancellationRequested();
  98.  
  99. TcpListener listener = new TcpListener(_serverConfiguration.ServerLicalAddress, _serverConfiguration.ServerPort);
  100.  
  101. listener.Start(_serverConfiguration.Backlog);
  102.  
  103. while (!cancellationToken.IsCancellationRequested)
  104. {
  105. if (_serverConfiguration.MaxConnections <= _clients.Count)
  106. {
  107. await Task.Delay(500);
  108. continue;
  109. }
  110.  
  111. var client = await listener.AcceptSocketAsync();
  112. Guid clientGuid = Guid.NewGuid();
  113. if (_clients.TryAdd(clientGuid, client))
  114. {
  115. _logger.LogInformation("Client accepted");
  116. }
  117. }
  118. }
  119. catch (OperationCanceledException)
  120. {
  121. _logger.LogInformation("Server stopped");
  122. }
  123. });
  124. acceptClientThread.Start();
  125. handleConnected.Start();
  126. }
  127.  
  128. public async Task SendToClient(Guid clientGuid, ReadOnlyMemory<byte> message, CancellationToken cancellationToken = default)
  129. {
  130. try
  131. {
  132. using var stream = new NetworkStream(_clients[clientGuid], false);
  133. {
  134. await stream.WriteAsync(message.ToArray(), 0, message.Length);
  135. }
  136. }
  137. catch (SocketException sex)
  138. {
  139. _logger.LogError(sex.ToString());
  140. }
  141. catch (Exception ex)
  142. {
  143. _logger.LogDebug(ex.ToString());
  144. }
  145. }
  146. public async Task BrodcastMessage(ReadOnlyMemory<byte> message, CancellationToken cancellationToken = default)
  147. {
  148. try
  149. {
  150. cancellationToken.ThrowIfCancellationRequested();
  151. var tasks = _clients.Where(x => x.Value.Connected).Select(x => SendToClient(x.Key, message, cancellationToken));
  152. await Task.WhenAll(tasks).ConfigureAwait(false);
  153. }
  154. catch (Exception ex)
  155. {
  156. _logger.LogError(ex.ToString());
  157. }
  158.  
  159. }
  160. }
  161. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cs(23,24): error CS1644: Feature `pattern matching' cannot be used because it is not part of the C# 7.0 language specification
prog.cs(28,37): error CS1644: Feature `pattern matching' cannot be used because it is not part of the C# 7.0 language specification
prog.cs(128,125): error CS1644: Feature `default literal' cannot be used because it is not part of the C# 7.0 language specification
prog.cs(132,22): error CS1525: Unexpected symbol `var', expecting `('
prog.cs(146,111): error CS1644: Feature `default literal' cannot be used because it is not part of the C# 7.0 language specification
Compilation failed: 5 error(s), 0 warnings
stdout
Standard output is empty