static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <SocketDatagramChannel>() .Option(ChannelOption.SoBroadcast, true) .Handler(new LoggingHandler("SRV-LSTN")) .Handler(new ActionChannelInitializer <ISocketChannel>(channel => { channel.Pipeline.AddLast("Quote", new QuoteOfTheMomentServerHandler()); })); IChannel boundChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.WriteLine("Press any key to terminate the server."); Console.ReadLine(); await boundChannel.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task RunServerAsync() { //设置输出日志到Console ExampleHelper.SetConsoleLogger(); // 主工作线程组,设置为1个线程 var bossGroup = new MultithreadEventLoopGroup(1); // 工作线程组,默认为内核数*2的线程数 var workerGroup = 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, workerGroup) // 设置主和工作线程组 .Channel <TcpServerSocketChannel>() // 设置通道模式为TcpSocket .Option(ChannelOption.SoBacklog, 100) // 设置网络IO参数等,这里可以设置很多参数,当然你对网络调优和参数设置非常了解的话,你可以设置,或者就用默认参数吧 .Handler(new LoggingHandler("SRV-LSTN")) //在主线程组上设置一个打印日志的处理器 .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { //工作线程连接器 是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输 //同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理 IChannelPipeline 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 EchoServerHandler()); })); // bootstrap绑定到指定端口的行为 就是服务端启动服务,同样的Serverbootstrap可以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))); } }
static async Task RunClientAsync() { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler( new ActionChannelInitializer <ISocketChannel>( channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new LoggingHandler()); pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("echo", new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); // 建立死循环,类同于While(true) for (; ;) // (4) { Console.WriteLine("input you data:"); // 根据设置建立缓存区大小 IByteBuffer initialMessage = Unpooled.Buffer(ClientSettings.Size); // (1) string r = Console.ReadLine(); // 将数据流写入缓冲区 initialMessage.WriteBytes(Encoding.UTF8.GetBytes(r ?? throw new InvalidOperationException())); // (2) // 将缓冲区数据流写入到管道中 await clientChannel.WriteAndFlushAsync(initialMessage); // (3) if (r.Contains("bye")) { break; } } Console.WriteLine("byebye"); await clientChannel.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); X509Certificate2 cert = null; string targetHost = null; if (Examples.Common.ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast(new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast(new BigIntegerDecoder()); pipeline.AddLast(new NumberEncoder()); pipeline.AddLast(new FactorialClientHandler()); })); IChannel bootstrapChannel = await bootstrap.ConnectAsync(new IPEndPoint(Examples.Common.ClientSettings.Host, Examples.Common.ClientSettings.Port)); // Get the handler instance to retrieve the answer. var handler = (FactorialClientHandler)bootstrapChannel.Pipeline.Last(); // Print out the answer. Console.WriteLine($"Factorial of {ClientSettings.Count} is: {handler.GetFactorial()}"); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { group.ShutdownGracefullyAsync().Wait(1000); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); var bossGroup = new MultithreadEventLoopGroup(1); var workerGroup = new MultithreadEventLoopGroup(); var stringEncoder = new StringEncoder(); var stringDecoder = new StringDecoder(); var serverHandler = new SecureChatServerHandler(); 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) .Channel <TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 100) .Handler(new LoggingHandler("LSTN")) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast(new DelimiterBasedFrameDecoder(8192, Delimiters.LineDelimiter())); pipeline.AddLast(stringEncoder, stringDecoder, serverHandler); })); IChannel bootstrapChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { Task.WaitAll(bossGroup.ShutdownGracefullyAsync(), workerGroup.ShutdownGracefullyAsync()); } }
static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); var bossGroup = new MultithreadEventLoopGroup(1); var 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); bootstrap.Channel <TcpServerSocketChannel>(); bootstrap.Option(ChannelOption.SoBacklog, 100); bootstrap.Handler(new LoggingHandler("SRV-LSTN")); bootstrap.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("echo", new EchoServerHandler()); pipeline.AddLast("User", new UserHandler()); // Action<string> messageTarget = ShowMessage; })); 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))); } }
static async Task RunClientAsync() { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { //Netty支持Tls加密传输,TlsHandler类可以在开发人员无须关心加密传输时字节码的变化,只关心自己的业务代码即可。在管道处理的第一个配置该类即可 pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast(new LoggingHandler()); //LengthFieldPrepender 会在实际发送前在将数据的长度放置在数据前,本例中使用2个字节来存储数据的长度。 pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); //LengthFieldBasedFrameDecoder 比较常用,会在解码前用于解析数据,用于读取数据包的头信息,特别是包长,并等待数据达到包长后再交由下一个handler处理。 参数说明 以下是Amp协议的参数值,并注释了意义 pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("echo", new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); Console.ReadLine(); await clientChannel.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2("dotnetty.com.pfx", "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast(new LoggingHandler()); pipeline.AddLast("framing-enc", new LengthFieldPrepender2(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("echo", new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); Console.ReadLine(); await clientChannel.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); var bossGroup = new MultithreadEventLoopGroup(1); var workerGroup = new MultithreadEventLoopGroup(); X509Certificate2 tlsCertificate = null; if (ServerSettings.IsSsl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "shared\\dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap .Group(bossGroup, workerGroup) .Channel <TcpServerSocketChannel>() .Option(ChannelOption.SoBacklog, 100) .Handler(new LoggingHandler("LSTN")) .ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (tlsCertificate != null) { pipeline.AddLast(TlsHandler.Server(tlsCertificate)); } pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast(new ProtobufVarint32FrameDecoder()); pipeline.AddLast(new ProtobufDecoder(Packet.DefaultInstance, RegistyExtensions())); pipeline.AddLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.AddLast(new ProtobufEncoder()); pipeline.AddLast(new RocketServerlHandler()); })); IChannel bootstrapChannel = await bootstrap.BindAsync(ServerSettings.Port); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { Task.WaitAll(bossGroup.ShutdownGracefullyAsync(), workerGroup.ShutdownGracefullyAsync()); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast(new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast(new LoggingHandler()); pipeline.AddLast(new DiscardClientHandler()); })); IChannel bootstrapChannel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); Console.ReadLine(); await bootstrapChannel.CloseAsync(); } finally { group.ShutdownGracefullyAsync().Wait(1000); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <SocketDatagramChannel>() .Option(ChannelOption.SoBroadcast, true) .Handler(new ActionChannelInitializer <IChannel>(channel => { channel.Pipeline.AddLast(new LoggingHandler("CONN")); channel.Pipeline.AddLast("Quote", new QuoteOfTheMomentClientHandler()); })); IChannel clientChannel = await bootstrap.BindAsync(IPEndPoint.MinPort); Console.WriteLine("Sending broadcast QOTM"); // Broadcast the QOTM request to port. byte[] bytes = Encoding.UTF8.GetBytes("QOTM?"); IByteBuffer buffer = Unpooled.WrappedBuffer(bytes); await clientChannel.WriteAndFlushAsync( new DatagramPacket( buffer, new IPEndPoint(IPAddress.Broadcast, ClientSettings.Port))); Console.WriteLine("Waiting for response."); await Task.Delay(5000); Console.WriteLine("Waiting for response time 5000 completed. Closing client channel."); await clientChannel.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
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; IEventLoopGroup bossGroup2 = null; IEventLoopGroup workGroup2 = null; if (useLibuv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workGroup = new WorkerEventLoopGroup(dispatcher); dispatcher = new DispatcherEventLoopGroup(); bossGroup2 = dispatcher; workGroup2 = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workGroup = new MultithreadEventLoopGroup(); } IChannel http2Channel = null; IChannel httpChannel = null; try { Http2Server http2 = useLibuv ? new Http2Server(bossGroup2, workGroup2) : new Http2Server(bossGroup, workGroup); http2Channel = await http2.StartAsync(); Console.WriteLine("Open your web browser and navigate to " + "http://127.0.0.1:" + HttpServer.PORT); HttpServer http = new HttpServer(bossGroup, workGroup); httpChannel = await http.StartAsync(); Console.WriteLine("按任意键退出"); Console.ReadKey(); } catch (Exception exc) { Console.WriteLine(exc.ToString()); Console.ReadKey(); } finally { if (http2Channel != null) { await http2Channel.CloseAsync(); } if (httpChannel != null) { await httpChannel.CloseAsync(); } if (workGroup2 != null) { await workGroup2.ShutdownGracefullyAsync(); } if (bossGroup2 != null) { await bossGroup2.ShutdownGracefullyAsync(); } await workGroup.ShutdownGracefullyAsync(); await bossGroup.ShutdownGracefullyAsync(); } }
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 { int port = ServerSettings.Port; IChannel bootstrapChannel = null; 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) .Handler(new LoggingHandler("LSTN")) //.Handler(new ServerChannelRebindHandler(DoBind)) .ChildHandler(new Http2ServerInitializer(tlsCertificate)); bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); //async void DoBind() //{ // await bootstrapChannel.CloseAsync(); // Console.WriteLine("rebind......"); // var ch = await bootstrap.BindAsync(IPAddress.Loopback, port); // Console.WriteLine("rebind complate"); // Interlocked.Exchange(ref bootstrapChannel, ch); //} Console.WriteLine("Open your HTTP/2-enabled web browser and navigate to " + (ServerSettings.IsSsl ? "https" : "http") + "://127.0.0.1:" + ServerSettings.Port + '/'); Console.WriteLine("Press any key to exit"); Console.ReadKey(); await bootstrapChannel.CloseAsync(); } finally { await Task.WhenAll( workGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)) ); } }
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(); } }
static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); IEventLoopGroup bossGroup; IEventLoopGroup workerGroup; bool useLibUv = false; bool isSSl = false; int serverPort = 8007; if (useLibUv) { var dispatcher = new DispatcherEventLoopGroup(); bossGroup = dispatcher; workerGroup = new WorkerEventLoopGroup(dispatcher); } else { bossGroup = new MultithreadEventLoopGroup(1); workerGroup = new MultithreadEventLoopGroup(); } X509Certificate2 tlsCertificate = null; if (isSSl) { tlsCertificate = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); } try { var bootstrap = new ServerBootstrap(); bootstrap.Group(bossGroup, workerGroup); if (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 EchoServerHandler()); })); IChannel boundChannel = await bootstrap.BindAsync(serverPort); 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 Main(string[] args) { ExampleHelper.SetConsoleLogger(); bool useLibuv = ClientSettings.UseLibuv; Console.WriteLine($"Transport type : {(useLibuv ? "Libuv" : "Socket")}"); IEventLoopGroup group; if (useLibuv) { group = new EventLoopGroup(); } else { group = new MultithreadEventLoopGroup(); } X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Option(ChannelOption.TcpNodelay, true); if (useLibuv) { bootstrap.Channel <TcpChannel>(); } else { bootstrap.Channel <TcpSocketChannel>(); } Http2ClientInitializer initializer = new Http2ClientInitializer(cert, targetHost, int.MaxValue); bootstrap.Handler(initializer); IChannel channel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); try { Console.WriteLine($"Connected to [{ClientSettings.Host}:{ClientSettings.Port}]"); // Wait for the HTTP/2 upgrade to occur. Http2SettingsHandler http2SettingsHandler = initializer.SettingsHandler; await http2SettingsHandler.AwaitSettings(TimeSpan.FromSeconds(5)); HttpResponseHandler responseHandler = initializer.ResponseHandler; int streamId = 3; HttpScheme scheme = ClientSettings.IsSsl ? HttpScheme.Https : HttpScheme.Http; AsciiString hostName = new AsciiString(ClientSettings.Host.ToString() + ':' + ClientSettings.Port); Console.WriteLine("Sending request(s)..."); var url = ExampleHelper.Configuration["url"]; var url2 = ExampleHelper.Configuration["url2"]; var url2Data = ExampleHelper.Configuration["url2data"]; if (!string.IsNullOrEmpty(url)) { // Create a simple GET request. IFullHttpRequest request = new DefaultFullHttpRequest(DotNetty.Codecs.Http.HttpVersion.Http11, HttpMethod.Get, url, Unpooled.Empty); request.Headers.Add(HttpHeaderNames.Host, hostName); request.Headers.Add(HttpConversionUtil.ExtensionHeaderNames.Scheme, scheme.Name); request.Headers.Add(HttpHeaderNames.AcceptEncoding, HttpHeaderValues.Gzip); request.Headers.Add(HttpHeaderNames.AcceptEncoding, HttpHeaderValues.Deflate); responseHandler.Put(streamId, channel.WriteAsync(request), channel.NewPromise()); streamId += 2; } if (!string.IsNullOrEmpty(url2)) { // Create a simple POST request with a body. IFullHttpRequest request = new DefaultFullHttpRequest(DotNetty.Codecs.Http.HttpVersion.Http11, HttpMethod.Post, url2, Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(url2Data))); request.Headers.Add(HttpHeaderNames.Host, hostName); request.Headers.Add(HttpConversionUtil.ExtensionHeaderNames.Scheme, scheme.Name); request.Headers.Add(HttpHeaderNames.AcceptEncoding, HttpHeaderValues.Gzip); request.Headers.Add(HttpHeaderNames.AcceptEncoding, HttpHeaderValues.Deflate); responseHandler.Put(streamId, channel.WriteAsync(request), channel.NewPromise()); } channel.Flush(); await responseHandler.AwaitResponses(TimeSpan.FromSeconds(5)); Console.WriteLine("Finished HTTP/2 request(s)"); Console.ReadKey(); } catch (Exception exception) { Console.WriteLine(exception.ToString()); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } finally { // Wait until the connection is closed. await channel.CloseAsync(); } } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
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))); } }
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(); } }
static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); // 申明一个主回路调度组 var dispatcher = new DispatcherEventLoopGroup(); /* * Netty 提供了许多不同的 EventLoopGroup 的实现用来处理不同的传输。 * 在这个例子中我们实现了一个服务端的应用,因此会有2个 NioEventLoopGroup 会被使用。 * 第一个经常被叫做‘boss’,用来接收进来的连接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上。 * 如何知道多少个线程已经被使用,如何映射到已经创建的 Channel上都需要依赖于 IEventLoopGroup 的实现,并且可以通过构造函数来配置他们的关系。 */ // 主工作线程组,设置为1个线程 IEventLoopGroup bossGroup = dispatcher; // (1) // 子工作线程组,设置为1个线程 IEventLoopGroup workerGroup = new WorkerEventLoopGroup(dispatcher); try { // 声明一个服务端Bootstrap,每个Netty服务端程序,都由ServerBootstrap控制,通过链式的方式组装需要的参数 var serverBootstrap = new ServerBootstrap(); // (2) // 设置主和工作线程组 serverBootstrap.Group(bossGroup, workerGroup); if (ServerSettings.UseLibuv) { // 申明服务端通信通道为TcpServerChannel serverBootstrap.Channel <TcpServerChannel>(); // (3) } serverBootstrap // 设置网络IO参数等 .Option(ChannelOption.SoBacklog, 100) // (5) // 在主线程组上设置一个打印日志的处理器 .Handler(new LoggingHandler("SRV-LSTN")) // 设置工作线程参数 .ChildHandler( /* * ChannelInitializer 是一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。 * 也许你想通过增加一些处理类比如DiscardServerHandler 来配置一个新的 Channel 或者其对应的ChannelPipeline 来实现你的网络程序。 * 当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上,然后提取这些匿名类到最顶层的类上。 */ new ActionChannelInitializer <IChannel>( // (4) channel => { /* * 工作线程连接器是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输, * 同时所有出栈的消息 也要这个管道的所有处理器进行一步步处理。 */ IChannelPipeline pipeline = channel.Pipeline; // 添加日志拦截器 pipeline.AddLast(new LoggingHandler("SRV-CONN")); // 添加出栈消息,通过这个handler在消息顶部加上消息的长度。 // LengthFieldPrepender(2):使用2个字节来存储数据的长度。 pipeline.AddLast("framing-enc", new LengthFieldPrepender(2)); /* * 入栈消息通过该Handler,解析消息的包长信息,并将正确的消息体发送给下一个处理Handler * 1,InitialBytesToStrip = 0, //读取时需要跳过的字节数 * 2,LengthAdjustment = -5, //包实际长度的纠正,如果包长包括包头和包体,则要减去Length之前的部分 * 3,LengthFieldLength = 4, //长度字段的字节数 整型为4个字节 * 4,LengthFieldOffset = 1, //长度属性的起始(偏移)位 * 5,MaxFrameLength = int.MaxValue, //最大包长 */ pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2)); // 业务handler pipeline.AddLast("echo", new EchoServerHandler()); })); // bootstrap绑定到指定端口的行为就是服务端启动服务,同样的Serverbootstrap可以bind到多个端口 IChannel boundChannel = await serverBootstrap.BindAsync(ServerSettings.Port); // (6) Console.WriteLine("wait the client input"); Console.ReadLine(); // 关闭服务 await boundChannel.CloseAsync(); } finally { // 释放指定工作组线程 await Task.WhenAll( // (7) bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)) ); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); bool useLibuv = ClientSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); IEventLoopGroup group; if (useLibuv) { group = new EventLoopGroup(); } else { group = new MultithreadEventLoopGroup(); } X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Option(ChannelOption.TcpNodelay, true) .Option(ChannelOption.SoKeepalive, true); if (useLibuv) { bootstrap.Channel <TcpChannel>(); } else { bootstrap.Channel <TcpSocketChannel>(); } bootstrap.Handler(new Http2ClientFrameInitializer(cert, targetHost)); IChannel channel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); try { Console.WriteLine("Connected to [" + ClientSettings.Host + ':' + ClientSettings.Port + ']'); Http2ClientStreamFrameResponseHandler streamFrameResponseHandler = new Http2ClientStreamFrameResponseHandler(); Http2StreamChannelBootstrap streamChannelBootstrap = new Http2StreamChannelBootstrap(channel); IHttp2StreamChannel streamChannel = await streamChannelBootstrap.OpenAsync(); streamChannel.Pipeline.AddLast(streamFrameResponseHandler); // Send request (a HTTP/2 HEADERS frame - with ':method = GET' in this case) var path = ExampleHelper.Configuration["path"]; HttpScheme scheme = ClientSettings.IsSsl ? HttpScheme.Https : HttpScheme.Http; DefaultHttp2Headers headers = new DefaultHttp2Headers { Method = HttpMethod.Get.AsciiName, Path = AsciiString.Of(path), Scheme = scheme.Name }; IHttp2HeadersFrame headersFrame = new DefaultHttp2HeadersFrame(headers); await streamChannel.WriteAndFlushAsync(headersFrame); Console.WriteLine("Sent HTTP/2 GET request to " + path); // Wait for the responses (or for the latch to expire), then clean up the connections if (!streamFrameResponseHandler.ResponseSuccessfullyCompleted()) { Console.WriteLine("Did not get HTTP/2 response in expected time."); } Console.WriteLine("Finished HTTP/2 request, will close the connection."); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.WriteLine("按任意键退出"); Console.ReadKey(); } finally { // Wait until the connection is closed. await channel.CloseAsync(); } } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task Main(string[] args) { var builder = new UriBuilder { Scheme = ClientSettings.IsSsl ? "wss" : "ws", Host = ClientSettings.Host.ToString(), Port = ClientSettings.Port, }; string path = ExampleHelper.Configuration["path"]; builder.Path = !string.IsNullOrEmpty(path) ? path : WEBSOCKET_PATH; Uri uri = builder.Uri; ExampleHelper.SetConsoleLogger(); bool useLibuv = ClientSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); IEventLoopGroup group; if (useLibuv) { group = new EventLoopGroup(); } else { group = new MultithreadEventLoopGroup(); } X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Option(ChannelOption.TcpNodelay, true); if (useLibuv) { bootstrap.Channel <TcpChannel>(); } else { bootstrap.Channel <TcpSocketChannel>(); } // Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00. // If you change it to V00, ping is not supported and remember to change // HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline. WebSocketClientHandler handler = new WebSocketClientHandler( WebSocketClientHandshakerFactory.NewHandshaker( uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders())); bootstrap.Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast("idleStateHandler", new IdleStateHandler(0, 0, 60)); pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast( new HttpClientCodec(), new HttpObjectAggregator(8192), WebSocketClientCompressionHandler.Instance, //new WebSocketClientProtocolHandler( // webSocketUrl: uri, // version: WebSocketVersion.V13, // subprotocol: null, // allowExtensions: true, // customHeaders: new DefaultHttpHeaders(), // maxFramePayloadLength: 65536, // handleCloseFrames: true, // performMasking: false, // allowMaskMismatch: true, // enableUtf8Validator: false), new WebSocketFrameAggregator(65536), handler); })); try { IChannel ch = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); await handler.HandshakeCompletion; Console.WriteLine("WebSocket handshake completed.\n"); Console.WriteLine("\t[bye]:Quit \n\t [ping]:Send ping frame\n\t Enter any text and Enter: Send text frame"); while (true) { string msg = Console.ReadLine(); if (msg == null) { break; } msg = msg.ToLowerInvariant(); switch (msg) { case "bye": await ch.WriteAndFlushAsync(new CloseWebSocketFrame()); goto CloseLable; case "ping": var ping = new PingWebSocketFrame(Unpooled.WrappedBuffer(new byte[] { 8, 1, 8, 1 })); await ch.WriteAndFlushAsync(ping); break; case "this is a test": await ch.WriteAndFlushManyAsync( new TextWebSocketFrame(false, "this "), new ContinuationWebSocketFrame(false, "is "), new ContinuationWebSocketFrame(false, "a "), new ContinuationWebSocketFrame(true, "test") ); break; case "this is a error": await ch.WriteAndFlushAsync(new TextWebSocketFrame(false, "this ")); await ch.WriteAndFlushAsync(new ContinuationWebSocketFrame(false, "is ")); await ch.WriteAndFlushAsync(new ContinuationWebSocketFrame(false, "a ")); await ch.WriteAndFlushAsync(new TextWebSocketFrame(true, "error")); break; default: await ch.WriteAndFlushAsync(new TextWebSocketFrame(msg)); break; } } CloseLable: await ch.CloseAsync(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.WriteLine("按任意键退出"); Console.ReadKey(); } } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task Main(string[] args) { ExampleHelper.SetConsoleLogger(); IEventLoopGroup bossGroup; IEventLoopGroup workerGroup; if (ServerSettings.UseLibuv) { ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; 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("dotnetty.com.pfx", "password"); } var serverHandler = new EchoServerHandler(); 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()) .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 LengthFieldPrepender2(2)); pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder2(ushort.MaxValue, 0, 2, 0, 2)); pipeline.AddLast("echo", serverHandler); })); 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))); } }
static async Task Main(string[] args) { var builder = new UriBuilder { Scheme = ClientSettings.IsSsl ? "https" : "http", Host = ClientSettings.Host.ToString(), Port = ClientSettings.Port, }; var baseUri = builder.Uri.ToString(); ExampleHelper.SetConsoleLogger(); string postSimple, postFile, get; if (baseUri.EndsWith("/")) { postSimple = baseUri + "formpost"; postFile = baseUri + "formpostmultipart"; get = baseUri + "formget"; } else { postSimple = baseUri + "/formpost"; postFile = baseUri + "/formpostmultipart"; get = baseUri + "/formget"; } var uriSimple = new Uri(postSimple); var uriFile = new Uri(postFile); bool useLibuv = ClientSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); IEventLoopGroup group; if (useLibuv) { group = new EventLoopGroup(); } else { group = new MultithreadEventLoopGroup(); } X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Option(ChannelOption.TcpNodelay, true); if (useLibuv) { bootstrap.Channel <TcpChannel>(); } else { bootstrap.Channel <TcpSocketChannel>(); } bootstrap.Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } //pipeline.AddLast(new LoggingHandler("CONN")); pipeline.AddLast("codec", new HttpClientCodec()); // Remove the following line if you don't want automatic content decompression. pipeline.AddLast("inflater", new HttpContentDecompressor()); // to be used since huge file transfer pipeline.AddLast("chunkedWriter", new ChunkedWriteHandler <IHttpContent>()); pipeline.AddLast("handler", new HttpUploadClientHandler()); })); // setup the factory: here using a mixed memory/disk based on size threshold var factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MinSize); // Disk if MINSIZE exceed DiskFileUpload.DeleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit) DiskFileUpload.FileBaseDirectory = null; // system temp directory DiskAttribute.DeleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit) DiskAttribute.DiskBaseDirectory = null; // system temp directory // Simple Get form: no factory used (not usable) var headers = await FormgetAsync(bootstrap, get, uriSimple); if (headers == null) { factory.CleanAllHttpData(); return; } using (var file = new FileStream("upload.txt", FileMode.Open, FileAccess.Read)) { // Simple Post form: factory used for big attributes var bodylist = await FormpostAsync(bootstrap, uriSimple, file, factory, headers); if (bodylist == null) { factory.CleanAllHttpData(); return; } // Multipart Post form: factory used await FormpostmultipartAsync(bootstrap, uriFile, factory, headers, bodylist); } Console.WriteLine("按任意键退出"); Console.ReadKey(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }
static async Task RunClientAsync() { ExampleHelper.SetConsoleLogger(); var group = new MultithreadEventLoopGroup(); X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel <TcpSocketChannel>() .Option(ChannelOption.TcpNodelay, true) .Handler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast(new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast(new DelimiterBasedFrameDecoder(8192, Delimiters.LineDelimiter())); pipeline.AddLast(new StringEncoder(), new StringDecoder(), new SecureChatClientHandler()); })); IChannel bootstrapChannel = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); for (;;) { string line = Console.ReadLine(); if (string.IsNullOrEmpty(line)) { continue; } try { await bootstrapChannel.WriteAndFlushAsync(line + "\r\n"); } catch { } if (string.Equals(line, "bye", StringComparison.OrdinalIgnoreCase)) { await bootstrapChannel.CloseAsync(); break; } } await bootstrapChannel.CloseAsync(); } finally { group.ShutdownGracefullyAsync().Wait(1000); } }
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")); string websocketPath = ExampleHelper.Configuration["path"]; websocketPath = !string.IsNullOrEmpty(websocketPath) ? websocketPath : WEBSOCKET_PATH; 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 { int port = ServerSettings.Port; IChannel bootstrapChannel = null; 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) //.Handler(new LoggingHandler("LSTN")) .Handler(new ServerChannelRebindHandler(DoBind)) .ChildHandler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (ServerSettings.IsSsl) { pipeline.AddLast(TlsHandler.Server(tlsCertificate, true)); } 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)); pipeline.AddLast(new WebSocketFrameAggregator(65536)); pipeline.AddLast(new WebSocketServerFrameHandler()); })); bootstrapChannel = await bootstrap.BindAsync(IPAddress.Loopback, port); async void DoBind() { await bootstrapChannel.CloseAsync(); Console.WriteLine("rebind......"); var ch = await bootstrap.BindAsync(IPAddress.Loopback, port); Console.WriteLine("rebind complate"); Interlocked.Exchange(ref bootstrapChannel, ch); } 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(); Console.WriteLine("close completion"); Console.WriteLine("按任意键退出"); Console.ReadKey(); } finally { await workGroup.ShutdownGracefullyAsync(); // (TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)); await bossGroup.ShutdownGracefullyAsync(); // (TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)); } }
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 RunClientAsync() { var builder = new UriBuilder { Scheme = ClientSettings.IsSsl ? "wss" : "ws", Host = ClientSettings.Host.ToString(), Port = ClientSettings.Port }; string path = ExampleHelper.Configuration["path"]; if (!string.IsNullOrEmpty(path)) { builder.Path = path; } Uri uri = builder.Uri; ExampleHelper.SetConsoleLogger(); bool useLibuv = ClientSettings.UseLibuv; Console.WriteLine("Transport type : " + (useLibuv ? "Libuv" : "Socket")); IEventLoopGroup group; if (useLibuv) { group = new EventLoopGroup(); } else { group = new MultithreadEventLoopGroup(); } X509Certificate2 cert = null; string targetHost = null; if (ClientSettings.IsSsl) { cert = new X509Certificate2(Path.Combine(ExampleHelper.ProcessDirectory, "dotnetty.com.pfx"), "password"); targetHost = cert.GetNameInfo(X509NameType.DnsName, false); } try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Option(ChannelOption.TcpNodelay, true); if (useLibuv) { bootstrap.Channel <TcpChannel>(); } else { bootstrap.Channel <TcpSocketChannel>(); } // Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00. // If you change it to V00, ping is not supported and remember to change // HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline. var handler = new WebSocketClientHandler( WebSocketClientHandshakerFactory.NewHandshaker( uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders())); bootstrap.Handler(new ActionChannelInitializer <IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; if (cert != null) { pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost))); } pipeline.AddLast( new HttpClientCodec(), new HttpObjectAggregator(8192), WebSocketClientCompressionHandler.Instance, handler); })); IChannel ch = await bootstrap.ConnectAsync(new IPEndPoint(ClientSettings.Host, ClientSettings.Port)); await handler.HandshakeCompletion; Console.WriteLine("WebSocket handshake completed.\n"); Console.WriteLine("\t[bye]:Quit \n\t [ping]:Send ping frame\n\t Enter any text and Enter: Send text frame"); while (true) { string msg = Console.ReadLine(); if (msg == null) { break; } else if ("bye".Equals(msg.ToLower())) { await ch.WriteAndFlushAsync(new CloseWebSocketFrame()); break; } else if ("ping".Equals(msg.ToLower())) { var frame = new PingWebSocketFrame(Unpooled.WrappedBuffer(new byte[] { 8, 1, 8, 1 })); await ch.WriteAndFlushAsync(frame); } else { WebSocketFrame frame = new TextWebSocketFrame(msg); await ch.WriteAndFlushAsync(frame); } } await ch.CloseAsync(); } finally { await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)); } }