IOTcpServer.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. namespace Universal.IO;
  2. internal class IOTcpServer : BaseFilter, ITcpServer
  3. {
  4. #region Internal Variables
  5. public string? Name { get; set; }
  6. private volatile bool _bInitialize = false;
  7. private volatile bool _bOpen = false;
  8. private volatile bool _bExit = false;
  9. private bool _noDelay = false;
  10. private int _receiveBufferSize = 0;
  11. private TcpListener? _tcpListener = null;
  12. private readonly HashSet<TcpClient> _clients = [];
  13. #endregion
  14. bool ITcpServer.Initialize(string name)
  15. {
  16. lock (this)
  17. {
  18. if (_bInitialize)
  19. return false;
  20. Name = name;
  21. _bInitialize = true;
  22. return true;
  23. }
  24. }
  25. bool ITcpServer.Open(string ip, ushort port, bool noDelay, int receiveBufferSize)
  26. {
  27. lock (this)
  28. {
  29. if (!_bInitialize)
  30. return false;
  31. if (_bOpen)
  32. return false;
  33. _bExit = false;
  34. IPAddress? address = IPAddress.Any;
  35. if (!string.IsNullOrWhiteSpace(ip))
  36. if (!IPAddress.TryParse(ip, out address))
  37. return false;
  38. TcpListener? tcpListener = null;
  39. try
  40. {
  41. tcpListener = new(address, port);
  42. tcpListener.Start();
  43. }
  44. catch
  45. {
  46. return false;
  47. }
  48. _noDelay = noDelay;
  49. _receiveBufferSize = receiveBufferSize;
  50. _tcpListener = tcpListener;
  51. TaskCompletionSource<bool> taskCompletionSource = new();
  52. Task.Factory.StartNew(() => WaitForConnection(taskCompletionSource), TaskCreationOptions.LongRunning);
  53. if (!taskCompletionSource.Task.Result)
  54. return false;
  55. _bOpen = true;
  56. return true;
  57. }
  58. }
  59. async Task WaitForConnection(TaskCompletionSource<bool>? taskCompletionSource = null)
  60. {
  61. if (_bExit)
  62. return;
  63. Task<System.Net.Sockets.TcpClient>? taskAcceptTcpClientAsync = default;
  64. try
  65. {
  66. taskAcceptTcpClientAsync = _tcpListener!.AcceptTcpClientAsync();
  67. taskCompletionSource?.SetResult(true);
  68. }
  69. catch
  70. {
  71. try { taskCompletionSource?.SetResult(false); } catch { }
  72. }
  73. try
  74. {
  75. System.Net.Sockets.TcpClient tcpClient = await taskAcceptTcpClientAsync!;
  76. tcpClient.NoDelay = _noDelay;
  77. if (_bExit)
  78. {
  79. tcpClient.Close();
  80. return;
  81. }
  82. NetworkStream networkStream = tcpClient.GetStream();
  83. if (tcpClient.Client.LocalEndPoint is not IPEndPoint || tcpClient.Client.RemoteEndPoint is not IPEndPoint)
  84. return;
  85. TcpConnection connection = new(
  86. (IPEndPoint)tcpClient.Client.LocalEndPoint!,
  87. (IPEndPoint)tcpClient.Client.RemoteEndPoint!,
  88. tcpClient);
  89. lock (_clients)
  90. _clients.Add(tcpClient);
  91. _ = Task.Factory.StartNew(async () => { try { await WaitForConnection(); } catch (Exception) { } }, TaskCreationOptions.LongRunning);
  92. try
  93. {
  94. try { PrevConnector?.Connected(connection); } catch { }
  95. for (byte[] buffer = new byte[_receiveBufferSize]; ;)
  96. {
  97. int bytesRead = 0;
  98. DateTime receiveTime;
  99. try
  100. {
  101. bytesRead = await networkStream.ReadAsync(buffer.AsMemory(0, _receiveBufferSize));
  102. receiveTime = DateTime.Now;
  103. }
  104. catch
  105. {
  106. break;
  107. }
  108. if (bytesRead <= 0)
  109. {
  110. lock (_clients)
  111. _clients.Remove(tcpClient);
  112. break;
  113. }
  114. byte[] cache = new byte[bytesRead];
  115. Array.Copy(buffer, cache, bytesRead);
  116. try { this.PrevReceiver?.Receive(new(cache, connection, receiveTime)); } catch { }
  117. }
  118. try
  119. {
  120. tcpClient.Close();
  121. PrevConnector?.Disconnected(connection);
  122. }
  123. catch { }
  124. }
  125. catch { }
  126. }
  127. catch { }
  128. }
  129. public override bool Send(Data data)
  130. {
  131. if (!_bInitialize)
  132. return false;
  133. if (!_bOpen)
  134. return false;
  135. if (data.Connection is not TcpConnection tcp)
  136. return false;
  137. if (tcp.TcpClient is null)
  138. return false;
  139. try
  140. {
  141. if (!tcp.TcpClient!.Connected)
  142. return false;
  143. if (data.RawData == null || data.RawData.Length == 0)
  144. return false;
  145. NetworkStream networkStream = tcp.TcpClient.GetStream();
  146. networkStream.Write([.. data.RawData], 0, data.RawData.Length);
  147. networkStream.Flush();
  148. data.DateTime = DateTime.Now;
  149. }
  150. catch
  151. {
  152. return false;
  153. }
  154. return true;
  155. }
  156. bool ITcpServer.Close()
  157. {
  158. lock (this)
  159. {
  160. if (!_bInitialize)
  161. return false;
  162. if (!_bOpen)
  163. return true;
  164. _bExit = true;
  165. try { _tcpListener?.Stop(); } catch { }
  166. lock (_clients)
  167. {
  168. foreach (System.Net.Sockets.TcpClient tcpClient in _clients)
  169. tcpClient.Close();
  170. _clients.Clear();
  171. }
  172. _bOpen = false;
  173. return true;
  174. }
  175. }
  176. public void Dispose()
  177. {
  178. (this as ITcpServer).Close();
  179. }
  180. }