首页 > 编程知识 正文

emacs完全教程,ubuntu完全教程

时间:2023-05-05 21:44:22 阅读:24779 作者:2925

第一个DotNetty APP应用程序准备工作NuGet包由9个项目组成,dot net ty在NuGet中是单独的包,可以根据需要进行引用。 其中重要的是:

DotNetty.Common是一个公用类库项目,包装线程池,包装并行任务和常规帮助类DotNetty.Transport是实现DotNetty核心的DotNetty.Buffers 包装内存缓冲区管理的DotNetty.Codes包装包含一些基类的编解码器我们在项目中定制的协议用于实现项目的特定基类和DotNetty.Handlers 如果项目中没有使用,也可以不参照。 但是,一般来说, 启动项目创建新的解决方案在NuGet上创建新的项目dot net ty.commondotnetty.transportdotnetty.buffers创建引用实例代码测试程序在回显测试APP应用程序中www.Sina.com/http://www.Sina.com/http://www.Sina.com/usingdotnetty.buffers; usingdotnetty.transport.channels; 用户系统; using System.Text; namespaceechoserver//summary//服务器只是响应传入的消息,因此,您只需要实现ChannelHandlerAdapter summarypublicclassechoserverhandler : channelhandleradapter (//summary///此方法//summmary )处理每个传入消息param name=' msg '/parampublicoverridevoidchannelread (接收iii控制台. writeline ('消息. tostring (编码) ) CTX.write async (消息); //summary//批量读取的最后一条消息是///summary//param name=' context '/parampublicoverridevoidchannelreadcomplete (////summmary/pary ) param name=' context '/param//param name=' exception '/parampublicoverridevoidexceptioncaught (ichannelhandlercontexcextion }}上述代码注释非常详细。 看评论,你应该知道这个班大概都做了什么,突然来的班还是有点难懂。 那么,我将以认真负责的精神,再详细说明一下没有学过Netty的同学难以理解的地方。 EchoServerHandler是为了什么? 回答:由于Netty封装了底层通信流程,所以我们不再需要担心网络底层问题(如套接字),我们现在可以集中精力处理业务。 什么是商业? 数据来了怎么办? Handler是一家处理数据的工厂。 那么,在上面的Handler上我们做了什么呢? 稍微分析一下,就会发现收到消息后,打印到控制台上,然后重新发送了消息

回去。问:WriteAsync 是在干什么?Flush 又是在干什么?答:由于是初学,不灌输太多,大家现在只需要知道数据写入之后并不会直接发出去,Flush的时候才会发出去。 在自动生成的Program.cs中写入服务器引导程序。using DotNetty.Transport.Bootstrapping;using DotNetty.Transport.Channels;using DotNetty.Transport.Channels.Sockets;using System;using System.Threading.Tasks;namespace EchoServer{ public class Program { static async Task RunServerAsync() { IEventLoopGroup eventLoop; eventLoop = new MultithreadEventLoopGroup(); try { // 服务器引导程序 var bootstrap = new ServerBootstrap(); bootstrap.Group(eventLoop); bootstrap.Channel<TcpServerSocketChannel>(); bootstrap.ChildHandler(new ActionChannelInitializer<IChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new EchoServerHandler()); })); IChannel boundChannel = await bootstrap.BindAsync(3000); Console.ReadLine(); await boundChannel.CloseAsync(); } catch (Exception ex) { Console.WriteLine(ex); } finally { await eventLoop.ShutdownGracefullyAsync(); } } static void Main(string[] args) => RunServerAsync().Wait(); }} 这个程序中同样有很多需要解释的,但是对于初学者来说,先明白这些概念就好了: bootstrap是启动引导的意思,Netty中的bootstrap的意思就是启动一个网络应用程序,那在启动之前我们肯定需要设置很多参数,bootstrap可以接收参数,引导用户启动Netty应用。EventLoopGroup 是一系列EventLoop的集合EventLoop 就对应了一个选择器(选择器看上一节的图)一个Channel都需要绑定到一个选择器(EventLoop)上每一个选择器(EventLoop)和一个线程绑定我们可以把Handler串起来处理数据,这个我们后面再讲,这里的做法是把Handler串到pipeline上。 再新建一个项目取名叫EchoClient新建一个类 EchoClientHandlerusing DotNetty.Buffers;using DotNetty.Transport.Channels;using System;using System.Text;namespace EchoClient{ public class EchoClientHandler : SimpleChannelInboundHandler<IByteBuffer> { /// <summary> /// Read0是DotNetty特有的对于Read方法的封装 /// 封装实现了: /// 1. 返回的message的泛型实现 /// 2. 丢弃非该指定泛型的信息 /// </summary> /// <param name="ctx"></param> /// <param name="msg"></param> protected override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg) { if (msg != null) { Console.WriteLine("Receive From Server:" + msg.ToString(Encoding.UTF8)); } ctx.WriteAsync(Unpooled.CopiedBuffer(msg)); } public override void ChannelReadComplete(IChannelHandlerContext context) { context.Flush(); } public override void ChannelActive(IChannelHandlerContext context) { Console.WriteLine("发送Hello World"); context.WriteAndFlushAsync(Unpooled.CopiedBuffer(Encoding.UTF8.GetBytes("Hello World!"))); } public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) { Console.WriteLine(exception); context.CloseAsync(); } }} Handler的编写方法于上面服务器的Handler基本一致,这里我们还是需要解释一些问题: SimpleChannelInboundHandler 继承自 ChannelHandlerAdapter,前者更强大的地方是对于资源的自动释放(这是一个伏笔)Read0方法在代码的注释中已经解释过了,有兴趣的同学可以看一下源码。这里我就不贴出来了ctx.WriteAsync(Unpooled.CopiedBuffer(msg));如果这里直接将msg发送出去,大家就会发现,实验失败了,这是为什么呢?简单解释就是因为引用计数器机制,IByteBuffer只能使用一次,而在我们使用Read0方法接收这个消息的时候,这个消息的引用计数就被归零了,这时候我们再次使用就会报出异常,所以这里需要将源消息再复制一份。当然,如果你使用的Read方法则不会有这样的问题。原则上来说,我们不应该存储指向任何消息的引用供未来使用,因为这些引用都会自动失效(意思就是消息收到了处理完就丢掉,消息不应该被长久保存)。 编写客户端引导程序using DotNetty.Transport.Bootstrapping;using DotNetty.Transport.Channels;using DotNetty.Transport.Channels.Sockets;using System;using System.Net;using System.Threading.Tasks;namespace EchoClient{ class Program { static async Task RunClientAsync() { var group = new MultithreadEventLoopGroup(); try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel<TcpSocketChannel>() .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse("10.10.10.158"), 3000)); Console.ReadLine(); await clientChannel.CloseAsync(); } catch (Exception ex) { Console.WriteLine(ex); } finally { await group.ShutdownGracefullyAsync(); } } static void Main(string[] args) => RunClientAsync().Wait(); }} 写在最后

项目的完整代码我放在了码云上,你可以点击这里可以下载。我相信很多完全没有接触过Netty的同学在跟着写完了第一个项目之后还是很懵,虽然解释了很多,但是还是感觉似懂非懂,这很正常。就如同我们写完HelloWorld之后,仍然会纠结一下static void Main(string[] args)为什么要这么写。我要说的是,只要坚持写完了第一个应用程序,你就是好样的,关于Netty我们还有很多很多要讲,相信你学了之后的知识以后,回过头来再看这个实例,会有恍然大悟的感觉。如果你坚持看完了文章并且敲了程序并且试验成功了,恭喜你,晚饭加个鸡腿,我们还有很多东西要学。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。