You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

99 line
4.5 KiB

  1. using DotNetty.Buffers;
  2. using DotNetty.Codecs;
  3. using DotNetty.Handlers.Timeout;
  4. using DotNetty.Transport.Bootstrapping;
  5. using DotNetty.Transport.Channels;
  6. using DotNetty.Transport.Libuv;
  7. using JT809.DotNetty.Core.Configurations;
  8. using Microsoft.Extensions.DependencyInjection;
  9. using Microsoft.Extensions.Hosting;
  10. using Microsoft.Extensions.Logging;
  11. using Microsoft.Extensions.Options;
  12. using System;
  13. using System.Net;
  14. using System.Runtime.InteropServices;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using JT809.Protocol;
  18. using JT809.DotNetty.Core.Codecs;
  19. using JT809.DotNetty.Core.Handlers;
  20. namespace JT809.DotNetty.Core.Services
  21. {
  22. /// <summary>
  23. /// JT809 Tcp网关服务
  24. /// </summary>
  25. internal class JT809MainServerHost : IHostedService
  26. {
  27. private readonly IServiceProvider serviceProvider;
  28. private readonly JT809Configuration configuration;
  29. private readonly ILogger<JT809MainServerHost> logger;
  30. private DispatcherEventLoopGroup bossGroup;
  31. private WorkerEventLoopGroup workerGroup;
  32. private IChannel bootstrapChannel;
  33. private IByteBufferAllocator serverBufferAllocator;
  34. private ILoggerFactory loggerFactory;
  35. public JT809MainServerHost(
  36. IServiceProvider provider,
  37. ILoggerFactory loggerFactory,
  38. IOptions<JT809Configuration> jT809ConfigurationAccessor)
  39. {
  40. serviceProvider = provider;
  41. configuration = jT809ConfigurationAccessor.Value;
  42. logger = loggerFactory.CreateLogger<JT809MainServerHost>();
  43. this.loggerFactory = loggerFactory;
  44. }
  45. public Task StartAsync(CancellationToken cancellationToken)
  46. {
  47. bossGroup = new DispatcherEventLoopGroup();
  48. workerGroup = new WorkerEventLoopGroup(bossGroup, configuration.EventLoopCount);
  49. serverBufferAllocator = new PooledByteBufferAllocator();
  50. ServerBootstrap bootstrap = new ServerBootstrap();
  51. bootstrap.Group(bossGroup, workerGroup);
  52. bootstrap.Channel<TcpServerChannel>();
  53. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
  54. || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
  55. {
  56. bootstrap
  57. .Option(ChannelOption.SoReuseport, true)
  58. .ChildOption(ChannelOption.SoReuseaddr, true);
  59. }
  60. bootstrap
  61. .Option(ChannelOption.SoBacklog, configuration.SoBacklog)
  62. .ChildOption(ChannelOption.Allocator, serverBufferAllocator)
  63. .ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
  64. {
  65. IChannelPipeline pipeline = channel.Pipeline;
  66. channel.Pipeline.AddLast("jt809MainBuffer", new DelimiterBasedFrameDecoder(int.MaxValue,
  67. Unpooled.CopiedBuffer(new byte[] { JT809Package.BEGINFLAG }),
  68. Unpooled.CopiedBuffer(new byte[] { JT809Package.ENDFLAG })));
  69. channel.Pipeline.AddLast("jt809MainSystemIdleState", new IdleStateHandler(
  70. configuration.ReaderIdleTimeSeconds,
  71. configuration.WriterIdleTimeSeconds,
  72. configuration.AllIdleTimeSeconds));
  73. pipeline.AddLast("jt809MainEncode", new JT809Encoder());
  74. pipeline.AddLast("jt809MainDecode", new JT809Decoder());
  75. channel.Pipeline.AddLast("jt809MainConnection", new JT809MainServerConnectionHandler(loggerFactory));
  76. using (var scope = serviceProvider.CreateScope())
  77. {
  78. channel.Pipeline.AddLast("jt809MainService", scope.ServiceProvider.GetRequiredService<JT809MainServerHandler>());
  79. }
  80. }));
  81. logger.LogInformation($"JT809 TCP Server start at {IPAddress.Any}:{configuration.TcpPort}.");
  82. return bootstrap.BindAsync(configuration.TcpPort)
  83. .ContinueWith(i => bootstrapChannel = i.Result);
  84. }
  85. public async Task StopAsync(CancellationToken cancellationToken)
  86. {
  87. await bootstrapChannel.CloseAsync();
  88. var quietPeriod = configuration.QuietPeriodTimeSpan;
  89. var shutdownTimeout = configuration.ShutdownTimeoutTimeSpan;
  90. await workerGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
  91. await bossGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
  92. }
  93. }
  94. }