DotnettyServer.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using DotNetty.Buffers;
  2. using DotNetty.Codecs;
  3. using DotNetty.Handlers.Logging;
  4. using DotNetty.Transport.Bootstrapping;
  5. using DotNetty.Transport.Channels;
  6. using DotNetty.Transport.Channels.Sockets;
  7. using Fody;
  8. using System;
  9. using System.Collections.Concurrent;
  10. using System.Collections.Generic;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using Team.Communicate.EventArg;
  14. using Team.Communicate.Handlers;
  15. namespace Team.Communicate.Server
  16. {
  17. // ReSharper disable once ClassNeverInstantiated.Global
  18. public class DotnettyServer : AbstractTcpConnector, IDisposable
  19. {
  20. private readonly ServerBootstrap _bootstrap = new();
  21. private readonly MultithreadEventLoopGroup _bossGroup = new(1);
  22. private readonly MultithreadEventLoopGroup _workerGroup = new();
  23. private IChannel _bootstrapChannel;
  24. private IChannelPipeline _channelPipeline;
  25. public ConcurrentDictionary<int, TcpStateEventArgs> ConnectionClients { get; }
  26. private bool _isInit;
  27. private readonly List<string> UseUngisterKeys = new();
  28. public event EventHandler<TcpStateEventArgs> ConnectionEvent;
  29. public event EventHandler<UnRegisterEventArgs> UnRegisterMessageEvent;
  30. private readonly TelnetServerHandler _serverHandler;
  31. public override Encoding Encoding
  32. {
  33. get => base.Encoding;
  34. set
  35. {
  36. base.Encoding = value;
  37. _serverHandler?.SetEncoding(value);
  38. }
  39. }
  40. public DotnettyServer()
  41. {
  42. ConnectionClients = new ConcurrentDictionary<int, TcpStateEventArgs>();
  43. Environment.SetEnvironmentVariable("io.netty.allocator.numDirectArenas", "0");
  44. _serverHandler = new TelnetServerHandler
  45. {
  46. Encoding = Encoding
  47. };
  48. }
  49. public override void SetEnd(string endWith)
  50. {
  51. base.SetEnd(endWith);
  52. _serverHandler.SetEndWith(endWith);
  53. }
  54. public override void UseUnRegisterMessage(string key)
  55. {
  56. if (UseUngisterKeys.Contains(key))
  57. {
  58. return;
  59. }
  60. UseUngisterKeys.Add(key);
  61. _serverHandler.SetUseUnRegisterKeys(UseUngisterKeys);
  62. }
  63. public override void Register(string id, Func<string, IChannelHandlerContext, ValueTask<string>> func)
  64. {
  65. _serverHandler.Register(id, func);
  66. }
  67. public override void UnRegister(string id)
  68. {
  69. _serverHandler.UnRegister(id);
  70. }
  71. public void ClearAllRegister()
  72. {
  73. _serverHandler.ClearAllRegister();
  74. }
  75. public void SetEventHandler(Func<string, IChannelHandlerContext, Task<string>> sendEventHandler)
  76. {
  77. }
  78. [ConfigureAwait(false)]
  79. public async Task<bool> StartAsync(int port)
  80. {
  81. if (_isInit)
  82. {
  83. return true;
  84. }
  85. var stringEncoder = new StringEncoder(Encoding);
  86. var stringDecoder = new StringDecoder(Encoding);
  87. _bootstrap
  88. .Group(_bossGroup, _workerGroup)
  89. .Channel<TcpServerSocketChannel>()
  90. .Option(ChannelOption.TcpNodelay, true)
  91. .Option(ChannelOption.SoBacklog, 100)
  92. .Handler(new LoggingHandler(LogLevel.INFO))
  93. .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
  94. {
  95. var pipeline = channel.Pipeline;
  96. _channelPipeline = pipeline;
  97. pipeline.AddLast(new DelimiterBasedFrameDecoder(8192, ByteBuffers));
  98. //pipeline.AddLast(stringEncoder, stringDecoder, _serverHandler);
  99. pipeline.AddLast("echo", _serverHandler);
  100. }));
  101. _serverHandler.ConnectionEvent += ServerHandler_ConnectionEvent;
  102. _serverHandler.UseUnRegisterAction += (s, e) =>
  103. {
  104. UnRegisterMessageEvent?.Invoke(this, new UnRegisterEventArgs(new UnRegisterContent(s, e, Encoding)));
  105. };
  106. try
  107. {
  108. _bootstrapChannel = await _bootstrap.BindAsync(port);
  109. _isInit = true;
  110. return _isInit;
  111. }
  112. catch (Exception e)
  113. {
  114. Console.WriteLine(e);
  115. throw;
  116. }
  117. }
  118. private void ServerHandler_ConnectionEvent(object sender, TcpStateEventArgs e)
  119. {
  120. var id = e.ServerConnection.GetHashCode();
  121. if (e.ServerConnection.Connected)
  122. {
  123. if (!ConnectionClients.ContainsKey(id))
  124. {
  125. ConnectionClients.TryAdd(id, e);
  126. }
  127. else
  128. {
  129. ConnectionClients[id] = e;
  130. }
  131. }
  132. else
  133. {
  134. if (ConnectionClients.ContainsKey(id))
  135. {
  136. ConnectionClients.TryRemove(id, out _);
  137. }
  138. }
  139. ConnectionEvent?.Invoke(this, e);
  140. }
  141. [ConfigureAwait(false)]
  142. public async Task SendMessage(string msg)
  143. {
  144. var stringBuilder = new StringBuilder();
  145. stringBuilder.Append(msg);
  146. stringBuilder.Append(_serverHandler._endWith);
  147. var bytes = Encoding.GetBytes(stringBuilder.ToString());
  148. var sendBytes = Unpooled.Buffer(256);
  149. sendBytes.WriteBytes(bytes);
  150. await _channelPipeline.WriteAndFlushAsync(sendBytes);
  151. //await _channelPipeline.WriteAndFlushAsync(msg + _serverHandler._endWith);
  152. }
  153. public async void Dispose()
  154. {
  155. try
  156. {
  157. if (_bootstrapChannel != null)
  158. {
  159. await _bootstrapChannel.Pipeline.DisconnectAsync();
  160. await _bootstrapChannel.Pipeline.CloseAsync();
  161. await _bootstrapChannel.DisconnectAsync();
  162. await _bootstrapChannel?.CloseAsync();
  163. }
  164. await _bossGroup.ShutdownGracefullyAsync();
  165. await _workerGroup.ShutdownGracefullyAsync();
  166. }
  167. catch (Exception e)
  168. {
  169. Console.WriteLine(e);
  170. }
  171. _isInit = false;
  172. }
  173. }
  174. }