一、DotNetty背景介紹
DotNetty是不但使用了C#和.Net平台的技術特點,並且保留了Netty原來絕大部分的編程接口。讓我們在使用時,完全可以依照Netty官方的教程來學習和使用DotNetty應用程序,接口文檔查看時對應代碼多看幾次,仔細閱讀。
DotNetty同時也是開源的,它的源代碼托管在Github上: https://github.com/azure/dotnetty
Netty 的官方文檔 : http://netty.io/wiki/all-documents.html
二、DotNetty項目各個程序集介紹
從Github網站下載的項目中我們比較關注的兩個文件夾,examples 和 src 。
examples中都是基本調用使用DotNetty的范例,src中是DotNetty的基礎源碼庫。我常用的是 Echo.Server 與 Echo.Client ,一個服務端,一個客戶端。
src 文件夾下的程序集介紹:
- DotNetty.Buffers
DotNetty.Buffers 是對內存緩沖區管理的封裝。
- DotNetty.Codecs
DotNetty.Codecs MQTT(消息隊列遙測傳輸)編解碼是封裝,包括一些基礎基類的實現。
- DotNetty.Codecs.ProtocolBuffers
ProtocolBuffers編解碼是封裝,包括一些基礎基類的實現。
- DotNetty.Common
DotNetty.Common 是公共的類庫項目,包裝線程池,並行任務和常用幫助類的封裝。
- DotNetty.Handlers
DotNetty.Transport 是DotNetty核心的實現,Socket基礎框架,通信模式:異步非阻塞。
- DotNetty.Transport.Libuv
DotNetty.Transport.Libuv是DotNetty自己實現基於Libuv (高性能的,事件驅動的I/O庫) 核心的實現。
三、代碼解釋:
// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
申明本文檔為個人閱讀文檔心得,如有解釋錯誤麻煩指教,所有心得均為推敲並未進行實測!
1.netty按照管道處理模式channl是總的通道及通訊通道本示例使用的是TcpServerSocketChannel,新版本還中有TcpServerChannel
2.ChildHandler中的通道可自定義執行順序可以在通道管理器中指定,收到消息第一站LengthFieldBasedFrameDecoder(是否先走日志通道不確定,)解析器可以自定義繼承響應的字節流父類就可以ByteToMessageDecoder
3.下一站即為EchoServerHandler,響應為IChannelHandlerContext context 中的 context.WriteAsync方法,
4.響應后會走LengthFieldPrepender中的 Encode方法在這里進行編碼
5.解析類型可按需求自定義,無需繼承
6.
//服務端: namespace Echo.Server { using System; using System.IO; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using DotNetty.Codecs; using DotNetty.Handlers.Logging; using DotNetty.Handlers.Tls; using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using Examples.Common; class Program { static async Task RunServerAsync() { ExampleHelper.SetConsoleLogger(); var bossGroup = new MultithreadEventLoopGroup(1);//多線程I/O事件循環器,接收 var workerGroup = new MultithreadEventLoopGroup();//多線程I/O事件循環器,將收的數據發送到worker 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>()//socket通訊通道 .Option(ChannelOption.SoBacklog, 100)//socket等等隊列長度 .Handler(new LoggingHandler("SRV-LSTN"))//日志通道 .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline;//通道管理器,可以自定義通道,繼承ChannelHandlerAdapter即可,執行順序可按照管理器中的其他方法指定 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(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 void Main() => RunServerAsync().Wait(); } }