ServerBootstrap SetupBootstrap() { int maxInboundMessageSize = this.settingsProvider.GetIntegerSetting("MaxInboundMessageSize", 256 * 1024); string connectionString = this.settings.IotHubConnectionString; if (connectionString.IndexOf("DeviceId=", StringComparison.OrdinalIgnoreCase) == -1) { connectionString += ";DeviceId=stub"; } var deviceClientFactory = new ThreadLocal <DeviceClientFactoryFunc>(() => { string poolId = Guid.NewGuid().ToString("N"); return(IotHubDeviceClient.PreparePoolFactory(connectionString, poolId, IotHubConnectionsPerThread)); }); return(new ServerBootstrap() .Group(this.parentEventLoopGroup, this.eventLoopGroup) .Option(ChannelOption.SoBacklog, ListenBacklogSize) .ChildOption(ChannelOption.Allocator, this.bufferAllocator) .ChildOption(ChannelOption.AutoRead, false) .Channel <TcpServerSocketChannel>() .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { channel.Pipeline.AddLast(TlsHandler.Server(this.tlsCertificate)); channel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, maxInboundMessageSize), new MqttIotHubAdapter( this.settings, deviceClientFactory.Value, this.sessionStateManager, this.authProvider, this.topicNameRouter, this.qos2StateProvider)); }))); }
/// <summary> /// /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task StartAsync(IEventLoopGroup BossGroup, IEventLoopGroup WorkerGroup, ServerOptions Options, AppFunc app) { X509Certificate2 tlsCertificate = null; if (Options.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(_environment.ContentRootPath, Options.CertificatePath), Options.CertificateToken); } var bootstrap = new ServerBootstrap(); var appKey = AttributeKey <AppFunc> .ValueOf(Constants.AppAttributeKey); bootstrap.Group(BossGroup, WorkerGroup) .Channel <TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 100) //设置channelconfig .Handler(new ActionChannelInitializer <IChannel>(channel => { this.Handler(channel, this._serviceProvider, Options); channel.Pipeline.AddLast(ActivatorUtilities.CreateInstance <TcpChannelGroupHandler>(this._serviceProvider, Options)); })) .ChildAttribute <AppFunc>(appKey, app) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { if (tlsCertificate != null) { channel.Pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } channel.Pipeline.AddLast(new IdleStateHandler(Options.Timeout, 0, 0)); channel.Pipeline.AddLast(new HeartBeatCheckHandler()); this.ChildHandler(channel, this._serviceProvider, Options); })); BoundChannel = await bootstrap.BindAsync(Options.Port); _logger.LogInformation($"{Options.Name}-Server-启动完成.端口号:{Options.Port}"); }
/// <summary> /// 创建服务端启动类 /// </summary> /// <typeparam name="T">消息处理类</typeparam> /// <param name="name">绑定通道名字</param> /// <param name="handler">处理实例</param> /// <param name="isSSL">是否ssl</param> /// <param name="certificateFileName">证书路径</param> /// <param name="certificatePwd">证书密码</param> /// <returns>服务端启动类</returns> public static ServerBootstrap CreateServerBootstrap <T>(string name, T handler, bool isSSL = false, string certificateFileName = null, string certificatePwd = null) where T : ChannelHandlerAdapter { IEventLoopGroup bossGroup = new MultithreadEventLoopGroup(100); IEventLoopGroup workerGroup = new MultithreadEventLoopGroup(5); try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); bootstrap .Channel <TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 100) .Handler(new LoggingHandler(LogLevel.INFO)) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (isSSL) { X509Certificate2 cert = null; cert = new X509Certificate2(certificateFileName, certificatePwd); pipeline.AddLast("tls", TlsHandler.Server(cert)); } pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast(name, handler); })); return(bootstrap); } catch (Exception ex) { LogUtil.Error(ex); Task.WaitAll(bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); throw; } }
ServerBootstrap SetupBootstrap() { if (this.settings.DeviceReceiveAckCanTimeout && this.iotHubClientSettings.MaxPendingOutboundMessages > 1) { throw new InvalidOperationException("Cannot maintain ordering on retransmission with more than 1 allowed pending outbound message."); } int maxInboundMessageSize = this.settingsProvider.GetIntegerSetting("MaxInboundMessageSize", 256 * 1024); int connectionPoolSize = this.settingsProvider.GetIntegerSetting("IotHubClient.ConnectionPoolSize", DefaultConnectionPoolSize); TimeSpan connectionIdleTimeout = this.settingsProvider.GetTimeSpanSetting("IotHubClient.ConnectionIdleTimeout", DefaultConnectionIdleTimeout); string connectionString = this.iotHubClientSettings.IotHubConnectionString; Func <IDeviceIdentity, Task <IMessagingServiceClient> > deviceClientFactory = IotHubClient.PreparePoolFactory(connectionString, connectionPoolSize, connectionIdleTimeout, this.iotHubClientSettings, PooledByteBufferAllocator.Default, this.topicNameConverter); MessagingBridgeFactoryFunc bridgeFactory = async deviceIdentity => new SingleClientMessagingBridge(deviceIdentity, await deviceClientFactory(deviceIdentity)); return(new ServerBootstrap() .Group(this.parentEventLoopGroup, this.eventLoopGroup) .Option(ChannelOption.SoBacklog, ListenBacklogSize) .ChildOption(ChannelOption.Allocator, PooledByteBufferAllocator.Default) .ChildOption(ChannelOption.AutoRead, false) .Channel <TcpServerSocketChannel>() .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { channel.Pipeline.AddLast(TlsHandler.Server(this.tlsCertificate)); channel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, maxInboundMessageSize), new MqttAdapter( this.settings, this.sessionStateManager, this.authProvider, this.qos2StateProvider, bridgeFactory)); }))); }
internal MqttTransportHandler(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { this.DefaultReceiveTimeout = DefaultReceiveTimeoutInSeconds; this.connectCompletion = new TaskCompletionSource(); this.mqttIotHubAdapterFactory = new MqttIotHubAdapterFactory(settings); this.messageQueue = new ConcurrentQueue <Message>(); this.completionQueue = new Queue <string>(); this.serverAddress = Dns.GetHostEntry(iotHubConnectionString.HostName).AddressList[0]; var group = new SingleInstanceEventLoopGroup(); this.qos = settings.PublishToServerQoS; this.bootstrap = new Bootstrap() .Group(@group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { ch.Pipeline.AddLast( TlsHandler.Client(iotHubConnectionString.HostName, null), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), this.mqttIotHubAdapterFactory.Create( this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); })); this.ScheduleCleanup(async() => { this.connectCompletion.TrySetCanceled(); await group.ShutdownGracefullyAsync(); }); }
public static async Task RunServerAsync() { //设置输出日志到Console UsualHelper.SetConsoleLogger(); // 主工作线程组,设置为1个线程 var bossGroup = new MultithreadEventLoopGroup(1); // 工作线程组,默认为内核数*2的线程数 var workerGroup = new MultithreadEventLoopGroup(); X509Certificate2 tlsCertificate = null; if (SevSettings.IsSsl) //如果使用加密通道 { tlsCertificate = new X509Certificate2(Path.Combine(UsualHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { //声明一个服务端Bootstrap,每个Netty服务端程序,都由ServerBootstrap控制, //通过链式的方式组装需要的参数 var bootstrap = new ServerBootstrap(); bootstrap .Group(bossGroup, workerGroup) // 设置主和工作线程组 .Channel <TcpServerSocketChannel>() // 设置通道模式为TcpSocket .Option(ChannelOption.SoBacklog, 100) // 设置网络IO参数等,这里可以设置很多参数,当然你对网络调优和参数设置非常了解的话,你可以设置,或者就用默认参数吧 .Handler(new LoggingHandler("SRV-LSTN")) //在主线程组上设置一个打印日志的处理器 .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { //工作线程连接器 是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输 //同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理 var pipeline = channel.Pipeline; if (tlsCertificate != null) //Tls的加解密 { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } //日志拦截器 pipeline.AddLast(new LoggingHandler("SRV-CONN")); //出栈消息,通过这个handler 在消息顶部加上消息的长度 pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); //入栈消息通过该Handler,解析消息的包长信息,并将正确的消息体发送给下一个处理Handler,该类比较常用,后面单独说明 pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); //业务handler ,这里是实际处理Echo业务的Handler pipeline.AddLast("echo", new WorkServerHandler()); })); // bootstrap绑定到指定端口的行为 就是服务端启动服务,同样的Serverbootstrap可以bind到多个端口 var boundChannel = await bootstrap.BindAsync(SevSettings.Port); Console.ReadLine(); //关闭服务 await boundChannel.CloseAsync(); } finally { //释放工作组线程 await Task.WhenAll( bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } }
static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); IEventLoopGroup bossGroup; IEventLoopGroup workerGroup; if (ServerSettings.UseLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workerGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workerGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); if (ServerSettings.UseLibuv) { bootstrap.Channel <TcpServerChannel>(); } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 100) .Handler(new LoggingHandler("SRV-LSTN")) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LoggingHandler("SRV-CONN")); pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("echo", new TestServerHandler()); })); IChannel boundChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.ReadLine(); await boundChannel.CloseAsync(); } finally { await Task.WhenAll( bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } }
public TlsHandlerWrapper(Func <Stream, SslStream> sslStreamFactory, TlsSettings settings) { handler = new TlsHandler(sslStreamFactory, settings); }
public bool Start(TcpChannelConfig channelConfig, ITcpListener listener) { #if !CLIENT if (channelConfig.UseLibuv) { ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workerGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workerGroup = new MultithreadEventLoopGroup(); } #else bossGroup = new MultithreadEventLoopGroup(1); workerGroup = new MultithreadEventLoopGroup(); #endif X509Certificate tlsCertificate = null; if (channelConfig.UseSSL) { tlsCertificate = new X509Certificate("dotnetty.com.pfx", "password"); } try { bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); #if !CLIENT if (channelConfig.UseLibuv) { bootstrap.Channel <TcpServerChannel>(); } else { bootstrap.Channel <TcpServerSocketChannel>(); } #else bootstrap.Channel <TcpServerSocketChannel>(); #endif bootstrap .Option(ChannelOption.SoBacklog, 8192) .Option(ChannelOption.SoReuseaddr, true) .Option(ChannelOption.SoReuseport, true) .Option(ChannelOption.SoBroadcast, true) .Option(ChannelOption.SoKeepalive, true) .Handler(new LoggingHandler()) .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LoggingHandler("SRV-CONN")); pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("tcp-handler", new TcpChannelHandler(listener)); })); var task = Task <IChannel> .Run(() => bootstrap.BindAsync(channelConfig.Address)); task.Wait(); boundChannel = task.Result; } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); return(false); } if (boundChannel == null) { return(false); } return(true); }
public async Task RunServerAsync() { logger.LogInformation($"{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}"); logger.LogInformation($"{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}"); logger.LogInformation($"Processor Count : {Environment.ProcessorCount}"); logger.LogInformation("Transport type : " + (serverConfiguration.Libuv ? "Libuv" : "Socket")); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } logger.LogInformation($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); logger.LogInformation($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); X509Certificate2 tlsCertificate = null; if (serverConfiguration.Ssl) { tlsCertificate = new X509Certificate2( Path.Combine(AppDomain.CurrentDomain.BaseDirectory, serverConfiguration.Certificate.Location), serverConfiguration.Certificate.Password); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(eventLoopGroups.BossGroup, eventLoopGroups.WorkerGroup); if (serverConfiguration.Libuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(webSockettHandler); })); int port = serverConfiguration.Port; IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); logger.LogInformation("Open your web browser and navigate to " + $"{(serverConfiguration.Ssl ? "https" : "http")}" + $"://{IPAddress.Loopback}:{port}/"); logger.LogInformation("Listening on " + $"{(serverConfiguration.Ssl ? "wss" : "ws")}" + $"://{IPAddress.Loopback}:{port}/websocket"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { eventLoopGroups.WorkerGroup.ShutdownGracefullyAsync().Wait(); eventLoopGroups.BossGroup.ShutdownGracefullyAsync().Wait(); } }
public async Task StartAsync(CancellationToken cancellationToken) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.SustainedLowLatency; } //if (_options.UseLibuv) //{ // var dispatcher = new DispatcherEventLoopGroup(); // _bossGroup = dispatcher; // _workerGroup = new WorkerEventLoopGroup(dispatcher); //} //else { // 主的线程 _bossGroup = new MultithreadEventLoopGroup(1); // 工作线程,默认根据CPU计算 _workerGroup = new MultithreadEventLoopGroup(); } var bootstrap = new ServerBootstrap() .Group(_bossGroup, _workerGroup); //if (_options.UseLibuv) { //bootstrap.Channel<TcpServerChannel>(); } //else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap.Option(ChannelOption.SoBacklog, _options.SoBacklog); //NOTE: 是否可以公开更多Netty的参数 if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } X509Certificate2 tlsCertificate = null; if (!string.IsNullOrEmpty(_options.Certificate)) { tlsCertificate = new X509Certificate2(_options.Certificate, _options.CertificatePassword); } _ = bootstrap.Handler(new LoggingHandler("LSTN")) .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { var pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LoggingHandler("CONN")); foreach (var kv in _handlerPipeline.BuildPipeline(true)) { pipeline.AddLast(kv.Key, kv.Value); } //业务处理Handler,即解码成功后如何处理消息的类 pipeline.AddLast(new TcpServerChannelHandlerAdapter <TMessage>(_socketService)); })); if (_options.BindType == AddressBindType.Any) { _channel = await bootstrap.BindAsync(_options.Port); } else if (_options.BindType == AddressBindType.InternalAddress) { var localPoint = IPUtility.GetLocalIntranetIP(); if (localPoint == null) { this._logger.LogWarning("there isn't an avaliable internal ip address,the service will be hosted at loopback address."); _channel = await bootstrap.BindAsync(IPAddress.Loopback, _options.Port); } else { //this._logger.LogInformation("TcpServerHost bind at {0}",localPoint); _channel = await bootstrap.BindAsync(localPoint, this._options.Port); } } else if (_options.BindType == AddressBindType.Loopback) { _channel = await bootstrap.BindAsync(IPAddress.Loopback, _options.Port); } else { _channel = await bootstrap.BindAsync(IPAddress.Parse(_options.SpecialAddress), _options.Port); } Console.Write(_options.StartupWords, _channel.LocalAddress); }
public async Task StartAsync(CancellationToken cancellationToken) { _Logger.LogInformation( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } _Logger.LogInformation($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); _Logger.LogInformation($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); string websocketPath = _Configuration.GetSection("WebSocket")["path"]; bool libuv = bool.Parse(_Configuration.GetSection("WebSocket")["libuv"]); int port = int.Parse(_Configuration.GetSection("WebSocket")["port"]); ssl = bool.Parse(_Configuration.GetSection("WebSocket")["ssl"]); if (libuv) { var dispatcher = new DispatcherEventLoopGroup(); _BossGroup = dispatcher; _WorkGroup = new WorkerEventLoopGroup(dispatcher); } else { _BossGroup = new MultithreadEventLoopGroup(1); _WorkGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ssl) { tlsCertificate = new X509Certificate2(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dotnetty.com.pfx"), "password"); } _BootstrapChannel = null; _Bootstrap = new ServerBootstrap(); _Bootstrap.Group(_BossGroup, _WorkGroup); if (libuv) { _Bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { _Bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { _Bootstrap.Channel <TcpServerSocketChannel>(); } _Bootstrap .Option(ChannelOption.SoBacklog, 8192) //.Handler(new LoggingHandler("LSTN")) .Handler(new ServerChannelRebindHandler(OnRebind)) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (ssl) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast("idleStateHandler", new IdleStateHandler(0, 0, 120)); //pipeline.AddLast(new LoggingHandler("CONN")); //pipeline.AddLast(new HttpRequestDecoder()); //pipeline.AddLast(new HttpResponseEncoder()); pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(new WebSocketServerCompressionHandler()); pipeline.AddLast(new WebSocketServerProtocolHandler( websocketPath: websocketPath, subprotocols: null, allowExtensions: true, maxFrameSize: 65536, allowMaskMismatch: true, checkStartsWith: false, dropPongFrames: true, enableUtf8Validator: false)); pipeline.AddLast(new WebSocketServerHttpHandler(websocketPath, _LoggerFactory)); pipeline.AddLast(new WebSocketFrameAggregator(65536)); pipeline.AddLast(new WebSocketServerFrameHandler(_ClusterClient, _LoggerFactory)); })); _BootstrapChannel = await _Bootstrap.BindAsync(IPAddress.Loopback, port); async void OnRebind() { await _BootstrapChannel.CloseAsync(); _Logger.LogInformation("rebind......"); var ch = await _Bootstrap.BindAsync(IPAddress.Loopback, port); _Logger.LogInformation("rebind complate"); Interlocked.Exchange(ref _BootstrapChannel, ch); } }
public async Task Listen() { var bootstrap = new ServerBootstrap(); if (_rpcOptions.UseLibuv) { var dispatcher = new DispatcherEventLoopGroup(); m_bossGroup = dispatcher; m_workerGroup = new WorkerEventLoopGroup(dispatcher); bootstrap.Channel <TcpServerChannel>(); } else { m_bossGroup = new MultithreadEventLoopGroup(1); m_workerGroup = new MultithreadEventLoopGroup(); bootstrap.Channel <TcpServerSocketChannel>(); } X509Certificate2 tlsCertificate = null; if (_rpcOptions.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(_hostEnvironment.ContentRootPath, _rpcOptions.SslCertificateName), _rpcOptions.SslCertificatePassword); } bootstrap .Option(ChannelOption.SoBacklog, _rpcOptions.SoBacklog) .ChildOption(ChannelOption.Allocator, PooledByteBufferAllocator.Default) .Group(m_bossGroup, m_workerGroup) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { var pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LengthFieldPrepender(8)); pipeline.AddLast(new LengthFieldBasedFrameDecoder(int.MaxValue, 0, 8, 0, 8)); pipeline.AddLast(new TransportMessageChannelHandlerAdapter(_transportMessageDecoder)); pipeline.AddLast(new ServerHandler((channelContext, message) => { if (message.IsInvokeMessage()) { var sender = new DotNettyTcpServerMessageSender(channelContext); OnReceived(sender, message); } }, _healthCheck)); })); try { m_boundChannel = await bootstrap.BindAsync(_hostAddress.IPEndPoint); Logger.LogInformation($"服务监听者启动成功,监听地址:{_hostAddress},通信协议:{_hostAddress.ServiceProtocol}"); } catch (Exception e) { Logger.LogError( $"服务监听启动失败,监听地址:{_hostAddress},通信协议:{_hostAddress.ServiceProtocol},原因: {e.Message}"); throw; } }
public override void Start() { Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); Console.WriteLine("\n"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); X509Certificate2 tlsCertificate = null; //if (ServerSettings.IsSsl) //{ // tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); //} try { bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); bootstrap.Channel <TcpServerSocketChannel>(); bootstrap .Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(new WebSocketServerHandler(this)); })); bootstrapChannel = bootstrap.BindAsync(IPAddress.Loopback, port).Result; Console.WriteLine("Open your web browser and navigate to " + $"{(false ? "https" : "http")}" + $"://127.0.0.1:{port}/"); Console.WriteLine("Listening on " + $"{(false ? "wss" : "ws")}" + $"://127.0.0.1:{port}/websocket"); //Console.ReadLine(); //bootstrapChannel.CloseAsync().Wait(); } finally { //workGroup.ShutdownGracefullyAsync().Wait(); //bossGroup.ShutdownGracefullyAsync().Wait(); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); bool useLibuv = ServerSettings.UseLibuv; Console.WriteLine($"Transport type :{(useLibuv ? "Libuv" : "Socket")}"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); Console.WriteLine("\n"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); if (useLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 1024) //.Handler(new LoggingHandler("LSTN")) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (ServerSettings.IsSsl) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } //pipeline.AddLast("idleStateHandler", new IdleStateHandler(0, 0, 120)); //pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast(new HttpRequestDecoder()); pipeline.AddLast(new HttpResponseEncoder()); //pipeline.AddLast(new HttpServerKeepAliveHandler()); // Remove the following line if you don't want automatic content compression. pipeline.AddLast(new HttpContentCompressor()); pipeline.AddLast(new HttpUploadServerHandler()); })); int port = ServerSettings.Port; IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); Console.WriteLine("Open your web browser and navigate to " + $"{(ServerSettings.IsSsl ? "https" : "http")}" + $"://127.0.0.1:{port}/"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); } }
public async Task RunServerAsync() { ConsoleHelper.ConDepServerWriteLine("持续部署服务启动中......"); ConsoleHelper.ConDepServerWriteLine($"电脑名称:{Environment.MachineName}"); ConsoleHelper.ConDepServerWriteLine($"系统版本:{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}"); ConsoleHelper.ConDepServerWriteLine($".NET版本:{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}"); ConsoleHelper.ConDepServerWriteLine($"CPU核心数:{Environment.ProcessorCount}"); ConsoleHelper.ConDepServerWriteLine("传输类型:" + (ApplicationConfig.WebSocketConfig.UserLibuv ? "Libuv" : "Socket")); ConsoleHelper.ConDepServerWriteLine($"服务垃圾回收机制:{(GCSettings.IsServerGC ? "服务" : "工作站")}"); ConsoleHelper.ConDepServerWriteLine($"垃圾回收延迟模式:{GCSettings.LatencyMode}"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (ApplicationConfig.WebSocketConfig.UserLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ApplicationConfig.WebSocketConfig.IsSsl) { tlsCertificate = new X509Certificate2(ApplicationConfig.WebSocketConfig.CertificatePath, ApplicationConfig.WebSocketConfig.CertificatePassword); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); if (ApplicationConfig.WebSocketConfig.UserLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap.Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap.Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(ApplicationConfig.WebSocketConfig.MaxMessageLength)); pipeline.AddLast(ApplicationData.GetService <WebSocketServerHandler>()); })); string hostName = Dns.GetHostName(); IPAddress[] ipAddresses = Dns.GetHostAddresses(hostName); ipAddresses = ipAddresses.Where(m => m.ToString().IsIPv4()).ToArray(); bool trueAddress = ipAddresses.Any(m => ApplicationConfig.WebSocketConfig.Host.Equals(m.ToString())); IPAddress ipAddress = trueAddress ? IPAddress.Parse(ApplicationConfig.WebSocketConfig.Host) : ipAddresses[0]; IChannel bootstrapChannel = await bootstrap.BindAsync(ipAddress, ApplicationConfig.WebSocketConfig.Port); ConsoleHelper.ConDepServerWriteLine("打开浏览器跳转到:" + $"{(ApplicationConfig.WebSocketConfig.IsSsl ? "https" : "http")}" + $"://{ipAddress}:{ApplicationConfig.WebSocketConfig.Port}/Login"); ConsoleHelper.ConDepServerWriteLine("监听中:" + $"{(ApplicationConfig.WebSocketConfig.IsSsl ? "wss" : "ws")}" + $"://{ipAddress}:{ApplicationConfig.WebSocketConfig.Port}/websocket"); ConsoleHelper.ConDepServerWriteLine("持续部署服务启动完毕"); ConsoleHelper.ConDepServerWriteLine("输入Stop停止服务"); string inputKey = string.Empty; while (!string.Equals(inputKey, "Stop", StringComparison.Ordinal)) { inputKey = Console.ReadLine(); } ConsoleHelper.ConDepServerWriteLine("正在停止服务....."); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); ConsoleHelper.ConDepServerWriteLine("服务已停止"); } }
static async Task RunServerAsync() { //设置输出日志到Console ExampleHelper.SetConsoleLogger(); // 主工作线程组 IEventLoopGroup bossGroup; // 工作线程组 IEventLoopGroup workerGroup; /* * IEventLoopGroup 是用来处理I/O操作的多线程事件循环器, * Netty 提供了许多不同的 EventLoopGroup 的实现用来处理不同的传输。 * 在这个例子中我们实现了一个服务端的应用,因此会有2个 NioEventLoopGroup 会被使用。 * 第一个经常被叫做‘boss’,用来接收进来的连接。第二个经常被叫做‘worker’。 * 用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上。 * 如何知道多少个线程已经被使用,如何映射到已经创建的 Channel上都需要依赖于 * IEventLoopGroup 的实现,并且可以通过构造函数来配置他们的关系。 */ if (ServerSettings.UseLibuv) { // 主工作线程组,设置为1个线程 var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; // 子工作线程组,设置为1个线程 workerGroup = new WorkerEventLoopGroup(dispatcher); } else { //设置为1个线程 bossGroup = new MultithreadEventLoopGroup(1); //默认为内核数*2的线程数 workerGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; //如果使用加密通道 if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { /* * 声明一个服务端Bootstrap,每个Netty服务端程序,都由ServerBootstrap控制, * 通过链式的方式组装需要的参数。 * ServerBootstrap 是一个启动 Transport 服务的辅助启动类。 * 你可以在这个服务中直接使用 Channel,但是这会是一个复杂的处理过程, * 在很多情况下你并不需要这样做。 */ var bootstrap = new ServerBootstrap(); // 设置主和工作线程组 bootstrap.Group(bossGroup, workerGroup); // 设置通道模式为TcpSocket if (ServerSettings.UseLibuv) { bootstrap.Channel <TcpServerChannel>(); } else { //这里我们指定使用 TcpServerChannel类来举例说明一个新的 Channel 如何接收进来的连接。 bootstrap.Channel <TcpServerSocketChannel>(); } // 设置网络IO参数等,这里可以设置很多参数,当然你对网络调优和参数设置非常了解的话,你可以设置,或者就用默认参数吧 //你可以设置这里指定的 Channel 实现的配置参数。我们正在写一个TCP/IP 的服务端,因此我们被允许设置 socket 的参数选项比如tcpNoDelay 和 keepAlive。 bootstrap.Option(ChannelOption.SoBacklog, 100) //初始化服务端可连接队列 //.Handler(new LoggingHandler("SRV-LSTN")) //在主线程组上设置一个打印日志的处理器 /* * ChannelInitializer 是一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。 * 也许你想通过增加一些处理类比如DiscardServerHandler 来配置一个新的 Channel, * 或者其对应的ChannelPipeline 来实现你的网络程序。 * 当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上, * 然后提取这些匿名类到最顶层的类上。 */ .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { //工作线程连接器 是设置了一个管道, //服务端主线程所有接收到的信息都会通过这个管道一层层往下传输 //同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理 IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) //Tls的加解密 { pipeline.AddLast("tls", TlsHandler.Server(tlsCertificate)); } //添加日志拦截器 //pipeline.AddLast(new LoggingHandler("SRV-CONN")); //出栈消息,通过这个handler 在消息顶部加上消息的长度 //LengthFieldPrepender(2):使用2个字节来存储数据的长度。 pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); /* * 自定义长度帧解码器 * 入栈消息通过该Handler,解析消息的包长信息,并将正确的消息体发送给下一个处理Handler * 1.MaxFrameLength = ushort.MaxValue,发送的数据包最大长度 * 2.LengthFieldOffset = 0,长度域偏移量,指的是长度域位于整个数据包字节数组中的下标。因为不存在包头,所以为0 * 3.LengthFieldLength = 2,长度域的自己的字节数长度,int整型为4个字节。Client出栈时添加两个字节,所以为2 * 4.LengthAdjustment = 0,长度域的偏移量矫正。 如果长度域的值,除了包含有效数据域的长度外,还包含了其他域(如长度域自身)长度,那么,就需要进行矫正。公式:包长 = 长度域偏移 + 长度域的值 + 长度域长 + 矫正值。 * 5.InitialBytesToStrip = 2,读取时需要跳过的字节数,Client出栈时添加2个字节数据长度 */ pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); //业务handler ,这里是实际处理Echo业务的Handler pipeline.AddLast("echo", new EchoServerHandler()); })); // bootstrap绑定到指定端口的行为 就是服务端启动服务,同样的Serverbootstrap可以bind到多个端口,多次调用 bind() 方法(基于不同绑定地址)。 IChannel boundChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.ReadLine(); //关闭服务 await boundChannel.CloseAsync(); } finally { //释放工作组线程 //使用完成后,优雅的释放掉指定的工作组线程,当然,你可以选择关闭程序,但这并不推荐。 await Task.WhenAll( bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } }
public async Task BasicFunctionalityTest() { await this.EnsureServerInitializedAsync(); int protocolGatewayPort = this.ProtocolGatewayPort; string iotHubConnectionString = ConfigurationManager.AppSettings["IoTHubConnectionString"]; IotHubConnectionStringBuilder hubConnectionStringBuilder = IotHubConnectionStringBuilder.Create(iotHubConnectionString); bool deviceNameProvided; this.deviceId = ConfigurationManager.AppSettings["End2End.DeviceName"]; if (!string.IsNullOrEmpty(this.deviceId)) { deviceNameProvided = true; } else { deviceNameProvided = false; this.deviceId = Guid.NewGuid().ToString("N"); } RegistryManager registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString); if (!deviceNameProvided) { await registryManager.AddDeviceAsync(new Device(this.deviceId)); this.ScheduleCleanup(async() => { await registryManager.RemoveDeviceAsync(this.deviceId); await registryManager.CloseAsync(); }); } Device device = await registryManager.GetDeviceAsync(this.deviceId); this.deviceSas = new SharedAccessSignatureBuilder { Key = device.Authentication.SymmetricKey.PrimaryKey, Target = string.Format("{0}/devices/{1}", hubConnectionStringBuilder.HostName, this.deviceId), KeyName = null, TimeToLive = TimeSpan.FromMinutes(20) } .ToSignature(); EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(iotHubConnectionString, "messages/events"); EventHubConsumerGroup ehGroup = eventHubClient.GetDefaultConsumerGroup(); string[] partitionIds = (await eventHubClient.GetRuntimeInformationAsync()).PartitionIds; EventHubReceiver[] receivers = await Task.WhenAll(partitionIds.Select(pid => ehGroup.CreateReceiverAsync(pid.Trim(), DateTime.UtcNow))); ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(iotHubConnectionString); Stopwatch sw = Stopwatch.StartNew(); var testPromise = new TaskCompletionSource(); var group = new MultithreadEventLoopGroup(); string targetHost = this.tlsCertificate.GetNameInfo(X509NameType.DnsName, false); Bootstrap bootstrap = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => ch.Pipeline.AddLast( TlsHandler.Client(targetHost, null, (sender, certificate, chain, errors) => true), MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), new TestScenarioRunner(cmf => GetClientScenario(cmf, hubConnectionStringBuilder.HostName, this.deviceId, this.deviceSas), testPromise, CommunicationTimeout, CommunicationTimeout), new XUnitLoggingHandler(this.output)))); IChannel clientChannel = await bootstrap.ConnectAsync(this.ServerAddress, protocolGatewayPort); this.ScheduleCleanup(async() => { await clientChannel.CloseAsync(); await group.ShutdownGracefullyAsync(); }); Task testWorkTask = Task.Run(async() => { Tuple <EventData, string>[] ehMessages = await CollectEventHubMessagesAsync(receivers, 2); Tuple <EventData, string> qos0Event = Assert.Single(ehMessages.Where(x => TelemetryQoS0Content.Equals(x.Item2, StringComparison.Ordinal))); //Assert.Equal((string)qos0Event.Item1.Properties["level"], "verbose"); //Assert.Equal((string)qos0Event.Item1.Properties["subject"], "n/a"); Tuple <EventData, string> qos1Event = Assert.Single(ehMessages.Where(x => TelemetryQoS1Content.Equals(x.Item2, StringComparison.Ordinal))); string qosPropertyName = ConfigurationManager.AppSettings["QoSPropertyName"]; var qos0Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS0Content)); qos0Notification.Properties[qosPropertyName] = "0"; qos0Notification.Properties["subTopic"] = "tips"; await serviceClient.SendAsync(this.deviceId, qos0Notification); var qos1Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS1Content)); qos1Notification.Properties["subTopic"] = "firmware-update"; await serviceClient.SendAsync(this.deviceId, qos1Notification); var qos2Notification = new Message(Encoding.UTF8.GetBytes(NotificationQoS2Content)); qos2Notification.Properties[qosPropertyName] = "2"; qos2Notification.Properties["subTopic"] = "critical-alert"; await serviceClient.SendAsync(this.deviceId, qos2Notification); }); Task timeoutTask = Task.Run(async() => { await Task.Delay(TestTimeout); throw new TimeoutException("Test has timed out."); }); await TaskExtensions.WhenSome(new[] { testPromise.Task, testWorkTask, timeoutTask }, 2); this.output.WriteLine(string.Format("Core test completed in {0}", sw.Elapsed)); // making sure that device queue is empty. await Task.Delay(TimeSpan.FromSeconds(3)); DeviceClient deviceClient = DeviceClient.Create( hubConnectionStringBuilder.HostName, new DeviceAuthenticationWithRegistrySymmetricKey(this.deviceId, device.Authentication.SymmetricKey.PrimaryKey)); Client.Message message = await deviceClient.ReceiveAsync(TimeSpan.FromSeconds(1)); Assert.True(message == null, string.Format("Message is not null: {0}", message)); }
static async Task RunServerAsync() { Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); bool useLibuv = ServerSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); Console.WriteLine("\n"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); if (useLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(new WebSocketServerHandler()); })); int port = ServerSettings.Port; IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); Console.WriteLine("Open your web browser and navigate to " + $"{(ServerSettings.IsSsl ? "https" : "http")}" + $"://127.0.0.1:{port}/"); Console.WriteLine("Listening on " + $"{(ServerSettings.IsSsl ? "wss" : "ws")}" + $"://127.0.0.1:{port}/websocket"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); } }
public async Task EchoServerAndClient() { var testPromise = new DefaultPromise(); var tlsCertificate = TestResourceHelper.GetTestCertificate(); Func <Task> closeServerFunc = await this.StartServerAsync(true, ch => { ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER")); ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate)); ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***")); ch.Pipeline.AddLast("server prepender", new LengthFieldPrepender2(2)); ch.Pipeline.AddLast("server decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); ch.Pipeline.AddLast(new EchoChannelHandler()); }, testPromise); var group = new MultithreadEventLoopGroup(); var readListener = new ReadListeningHandler(DefaultTimeout); Bootstrap b = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var clientTlsSettings = new ClientTlsSettings(targetHost); ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT")); ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings)); ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***")); ch.Pipeline.AddLast("client prepender", new LengthFieldPrepender2(2)); ch.Pipeline.AddLast("client decoder", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); ch.Pipeline.AddLast(readListener); })); this.Output.WriteLine("Configured Bootstrap: {0}", b); IChannel clientChannel = null; try { clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port); this.Output.WriteLine("Connected channel: {0}", clientChannel); string[] messages = { "message 1", string.Join(",", Enumerable.Range(1, 300)) }; foreach (string message in messages) { await clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(message))).WithTimeout(DefaultTimeout); var responseMessage = Assert.IsAssignableFrom <IByteBuffer>(await readListener.ReceiveAsync()); Assert.Equal(message, responseMessage.ToString(Encoding.UTF8)); } testPromise.TryComplete(); await testPromise.Task.WithTimeout(TimeSpan.FromMinutes(5)); } finally { Task serverCloseTask = closeServerFunc(); clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5)); group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10)); if (!serverCloseTask.Wait(ShutdownTimeout)) { this.Output.WriteLine("Didn't stop in time."); } } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); bool useLibuv = ServerSettings.UseLibuv; Console.WriteLine($"Transport type : {(useLibuv ? "Libuv" : "Socket")}"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection: {GCSettings.IsServerGC}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); IEventLoopGroup group; IEventLoopGroup workGroup; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); group = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { group = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(group, workGroup); if (useLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 200) #if DEBUG .Handler(new LoggingHandler("LSTN")) #endif .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } #if DEBUG pipeline.AddLast(new LoggingHandler("CONN")); #endif //pipeline.AddLast("encoder", new HttpResponseEncoder()); //pipeline.AddLast("decoder", new HttpRequestDecoder(4096, 8192, 8192, false)); pipeline.AddLast(new HttpServerCodec(4096, 8192, 8192, false)); //pipeline.AddLast(new HttpObjectAggregator(65536)); pipeline.AddLast(new HttpServerExpectContinueHandler()); pipeline.AddLast("handler", new HelloServerHandler()); })); IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.IPv6Any, ServerSettings.Port); Console.WriteLine($"Httpd started. Listening on {bootstrapChannel.LocalAddress}"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { group.ShutdownGracefullyAsync().Wait(); } }
Func <IPAddress, int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { #if WINDOWS_UWP return(async(address, port) => { PlatformProvider.Platform = new UWPPlatform(); var eventLoopGroup = new MultithreadEventLoopGroup(); var streamSocket = new StreamSocket(); await streamSocket.ConnectAsync(new HostName(iotHubConnectionString.HostName), port.ToString(), SocketProtectionLevel.PlainSocket); streamSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); await streamSocket.UpgradeToSslAsync(SocketProtectionLevel.Tls12, new HostName(iotHubConnectionString.HostName)); var streamSocketChannel = new StreamSocketChannel(streamSocket); streamSocketChannel.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); streamSocketChannel.Configuration.SetOption(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default); await eventLoopGroup.GetNext().RegisterAsync(streamSocketChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return streamSocketChannel; }); #else return((address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); var clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List <X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(eventLoopGroup) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { var tlsHandler = new TlsHandler(streamFactory, clientTlsSettings); ch.Pipeline .AddLast( tlsHandler, MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); })); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return bootstrap.ConnectAsync(address, port); }); #endif }
public async Task MqttServerAndClient() { var testPromise = new DefaultPromise(); var tlsCertificate = TestResourceHelper.GetTestCertificate(); var serverReadListener = new ReadListeningHandler(); IChannel serverChannel = null; Func <Task> closeServerFunc = await this.StartServerAsync(true, ch => { serverChannel = ch; ch.Pipeline.AddLast("server logger", new LoggingHandler("SERVER")); ch.Pipeline.AddLast("server tls", TlsHandler.Server(tlsCertificate)); ch.Pipeline.AddLast("server logger2", new LoggingHandler("SER***")); ch.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(true, 256 * 1024), serverReadListener); }, testPromise); var group = new MultithreadEventLoopGroup(); var clientReadListener = new ReadListeningHandler(); Bootstrap b = new Bootstrap() .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false); var clientTlsSettings = new ClientTlsSettings(targetHost); ch.Pipeline.AddLast("client logger", new LoggingHandler("CLIENT")); ch.Pipeline.AddLast("client tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), clientTlsSettings)); ch.Pipeline.AddLast("client logger2", new LoggingHandler("CLI***")); ch.Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, 256 * 1024), clientReadListener); })); this.Output.WriteLine("Configured Bootstrap: {0}", b); IChannel clientChannel = null; try { clientChannel = await b.ConnectAsync(IPAddress.Loopback, Port); this.Output.WriteLine("Connected channel: {0}", clientChannel); await Task.WhenAll(this.RunMqttClientScenarioAsync(clientChannel, clientReadListener), this.RunMqttServerScenarioAsync(serverChannel, serverReadListener)) .WithTimeout(TimeSpan.FromMinutes(5)); testPromise.TryComplete(); await testPromise.Task; } finally { Task serverCloseTask = closeServerFunc(); clientChannel?.CloseAsync().Wait(TimeSpan.FromSeconds(5)); group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)).Wait(TimeSpan.FromSeconds(10)); if (!serverCloseTask.Wait(ShutdownTimeout)) { this.Output.WriteLine("Didn't stop in time."); } } }
public Boolean Init(ConnectionListener <MQMessage> listener) { if (channel == null) { bootstrap = new Bootstrap(); loopGroup = new MultithreadEventLoopGroup(workerThreads); bootstrap.Group(loopGroup); bootstrap.Channel <TcpSocketChannel>(); bootstrap.Option(ChannelOption.TcpNodelay, true); bootstrap.Option(ChannelOption.SoKeepalive, true); X509Certificate2 cert = null; if (certificate != null && certificate.Length > 0) { cert = CertificatesHelper.load(certificate, certificatePassword); } WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.NewHandshaker(this.getUri(), WebSocketVersion.V13, null, false, EmptyHttpHeaders.Default, 1280000); WebSocketClientHandler handler = new WebSocketClientHandler(this, handshaker, listener); bootstrap.Handler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (isSecured) { if (cert != null) { pipeline.AddLast("ssl", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true, (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => cert), new ClientTlsSettings(address.Host, new List <X509Certificate>() { cert }))); } else { pipeline.AddLast("ssl", TlsHandler.Client(address.Host)); } } pipeline.AddLast("http - codec", new HttpClientCodec()); pipeline.AddLast("aggregator", new HttpObjectAggregator(65536)); pipeline.AddLast("handler", handler); pipeline.AddLast(new ExceptionHandler()); })); bootstrap.RemoteAddress(address); try { Task <IChannel> task = bootstrap.ConnectAsync(); task.GetAwaiter().OnCompleted(() => { try { channel = task.Result; } catch (Exception) { listener.ConnectFailed(); return; } if (channel != null) { listener.Connected(); } else { listener.ConnectFailed(); } }); } catch (Exception) { return(false); } } return(true); }
Func <IPAddress[], int, Task <IChannel> > CreateChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, ProductInfo productInfo) { return(async(addresses, port) => { IChannel channel = null; Func <Stream, SslStream> streamFactory = stream => new SslStream(stream, true, settings.RemoteCertificateValidationCallback); var clientTlsSettings = settings.ClientCertificate != null ? new ClientTlsSettings(iotHubConnectionString.HostName, new List <X509Certificate> { settings.ClientCertificate }) : new ClientTlsSettings(iotHubConnectionString.HostName); Bootstrap bootstrap = new Bootstrap() .Group(s_eventLoopGroup) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Handler(new ActionChannelInitializer <ISocketChannel>(ch => { var tlsHandler = new TlsHandler(streamFactory, clientTlsSettings); ch.Pipeline .AddLast( tlsHandler, MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings, productInfo)); })); foreach (IPAddress address in addresses) { try { if (Logging.IsEnabled) { Logging.Info(this, $"Connecting to {address.ToString()}", nameof(CreateChannelFactory)); } channel = await bootstrap.ConnectAsync(address, port).ConfigureAwait(false); break; } catch (AggregateException ae) { ae.Handle((ex) => { if (ex is ConnectException) // We will handle DotNetty.Transport.Channels.ConnectException { if (Logging.IsEnabled) { Logging.Error(this, $"ConnectException trying to connect to {address.ToString()}: {ex.ToString()}", nameof(CreateChannelFactory)); } return true; } return false; // Let anything else stop the application. }); } } return channel; }); }
public SslHandlerCoalescingBufferQueue(TlsHandler owner, IChannel channel, int initSize) : base(channel, initSize) { _owner = owner; }
//private void CheckOnRemoteCert() //{ // Task.Run(() => // { // bool stillNoCert = true; // while(stillNoCert) // { // try // { // if (RemoteCertificate != null) // { // stillNoCert = false; // Console.WriteLine("Found the cert!"); // } // } // catch { } // } // }); //} public TlsHandlerWrapper(TlsSettings settings) { handler = new DotNetty.Handlers.Tls.TlsHandler(settings); }
public async Task RunServerAsync(ServerConfigModel configModel) { Console.WriteLine("WebSocket服务器启动"); Console.WriteLine( $"系统版本:{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}\r\n" + $".NET版本:{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}\r\n" + $"CPU核心数:{Environment.ProcessorCount}"); Console.WriteLine("传输类型:" + (configModel.UserLibuv ? "Libuv" : "Socket")); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"服务器垃圾回收机制:{(GCSettings.IsServerGC ? "启用" : "禁用")}"); Console.WriteLine($"垃圾回收延迟模式:{GCSettings.LatencyMode}"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (configModel.UserLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (configModel.IsSsl) { tlsCertificate = new X509Certificate2(configModel.CertificatePath, configModel.CertificatePassword); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workGroup); if (configModel.UserLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap.Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap.Option(ChannelOption.SoBacklog, 8192) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); if (configModel.ServerHandler is BaseDotNettyServerHandler serverHandler) { pipeline.AddLast(serverHandler); } })); IPAddress iPAddress = IPAddress.Parse(configModel.Host); IChannel bootstrapChannel = await bootstrap.BindAsync(iPAddress, configModel.Port); Console.WriteLine("打开你的浏览器跳转到:" + $"{(configModel.IsSsl ? "https" : "http")}" + $"://{iPAddress}:{configModel.Port}/api"); Console.WriteLine("监听中:" + $"{(configModel.IsSsl ? "wss" : "ws")}" + $"://{iPAddress}:{configModel.Port}/websocket"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); } }
public static async Task RunServerAsync() { //在控制台命令中启用日志 ExampleHelper.SetConsoleLogger(); //多线程事件循环组,创建一个新实例,老板组 var bossGroup = new MultithreadEventLoopGroup(1); //多线程事件循环组,创建一个新实例,工作组 var workerGroup = new MultithreadEventLoopGroup(); //字符串编码 var STRING_ENCODER = new StringEncoder(); //字符串解码 var STRING_DECODER = new StringDecoder(); //安全聊天服务器处理程序 var SERVER_HANDLER = new SecureChatServerHandler(); X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { // 创建 X.509 证书 tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { //服务器启动 var bootstrap = new ServerBootstrap(); bootstrap .Group(bossGroup, workerGroup) //服务器套接字通道 .Channel <TcpServerSocketChannel>() //所以返回日志 .Option(ChannelOption.SoBacklog, 100) //Handler用于服务请求 “信息”日志级别。 .Handler(new LoggingHandler(LogLevel.INFO)) //设置{@链接channelhandler }这是用来服务请求{@链接通道}的。 .ChildHandler( new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { //添加协议到最后 pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } //添加基于行分隔符的帧解码器到最后 pipeline.AddLast(new DelimiterBasedFrameDecoder(8192, Delimiters.LineDelimiter())); pipeline.AddLast(STRING_ENCODER, STRING_DECODER, SERVER_HANDLER); })); // 创建异步通道并绑定异步端口 IChannel bootstrapChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.ReadLine(); //关闭异步 await bootstrapChannel.CloseAsync(); } finally { // 等待提供的所有 System.Threading.Tasks.Task 对象完成执行过程 Task.WaitAll(bossGroup.ShutdownGracefullyAsync(), workerGroup.ShutdownGracefullyAsync()); } }
static async Task RunServerAsync() { Console.WriteLine( $"\n{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}" + $"\n{RuntimeInformation.ProcessArchitecture} {RuntimeInformation.FrameworkDescription}" + $"\nProcessor Count : {Environment.ProcessorCount}\n"); bool useLibuv = ServerSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; } Console.WriteLine($"Server garbage collection : {(GCSettings.IsServerGC ? "Enabled" : "Disabled")}"); Console.WriteLine($"Current latency mode for garbage collection: {GCSettings.LatencyMode}"); Console.WriteLine("\n"); IEventLoopGroup bossGroup; IEventLoopGroup workGroup; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); } else { //其实质是实例化一个SingleThreadEventLoop对象,负责接收新连接 bossGroup = new MultithreadEventLoopGroup(1); //其实质是实例化当前处理器*2个SingleThreadEventLoop对象,不断循环接收新消息 workGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { //声明一个服务端Bootstrap,每个Netty服务端程序,都由ServerBootstrap控制,通过链式的方式组装需要的参数 var bootstrap = new ServerBootstrap(); //设置主和工作线程组 bootstrap.Group(bossGroup, workGroup); if (useLibuv) { bootstrap.Channel <TcpServerChannel>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { bootstrap .Option(ChannelOption.SoReuseport, true) .ChildOption(ChannelOption.SoReuseaddr, true); } } else { //声明服务端通信通道为TcpServerSocketChannel bootstrap.Channel <TcpServerSocketChannel>(); } bootstrap .Option(ChannelOption.SoBacklog, 8192) /* * ChannelInitializer 是一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。 * 也许你想通过增加一些处理类比如DiscardServerHandler 来配置一个新的 Channel 或者其对应的ChannelPipeline 来实现你的网络程序。 * 当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上,然后提取这些匿名类到最顶层的类上。 */ .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { /* * 工作线程连接器是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输, * 同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理。 */ IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new HttpServerCodec()); pipeline.AddLast(new HttpObjectAggregator(65536)); // 业务handler pipeline.AddLast(new WebSocketServerHandler()); })); int port = ServerSettings.Port; // bootstrap绑定到指定端口的行为就是服务端启动服务,同样的Serverbootstrap可以bind到多个端口 IChannel bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); Console.WriteLine("Open your web browser and navigate to " + $"{(ServerSettings.IsSsl ? "https" : "http")}" + $"://127.0.0.1:{port}/"); Console.WriteLine("Listening on " + $"{(ServerSettings.IsSsl ? "wss" : "ws")}" + $"://127.0.0.1:{port}/websocket"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { workGroup.ShutdownGracefullyAsync().Wait(); bossGroup.ShutdownGracefullyAsync().Wait(); } }