DotNetty项目基本了解和介绍
一、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(); } }