• Netty快速入门(07)Netty入门例子


    回顾NIO编程

    在正式学习netty之前,我们先来回顾一下NIO编程。NIO代码是比较麻烦和复杂的,大家可以考虑一下,如果让我们自己封装NIO,哪些角度和部分是需要考虑的?如何简化编程?

    我们使用NIO的时候,服务端的编程流程可以大致总结如下:

    1、创建Selector

    2、创建ServerSocketChannel,注册到Selector上,并关注Accept事件

    3、获取就绪的channel,然后开始while循环,处理关注类型的事件

    4、处理Accept事件

    5、处理read事件

    6、处理write事件

    。。。

    根据上面可以总结,肯定会有一个选择器,有一个接收线程,有一个事件循环处理关注的内容,在循环中,针对不同的类型,有一套处理的流程。比如处理Accept事件的时候,流程基本是固定的:

    file

    至于read或者write事件,就是和业务密切相关了,不同的业务请求,如何读或者写,都不是固定的一套。但是如果仔细分析的话,也是可以提取一部分公共流程的,比如刚开始基本上都是读取流和解码,然后是处理各自不同的业务,处理完后就是编码和发送返回内容。基本上可以分为这五个步骤:

    读取

    解码

    处理业务

    编码

    发送

    如果我们写框架也是这样,把公共的部分会提取出来,模板化,让使用人大部分时候只关注中间的业务处理流程。

    开始Netty服务端编程

    上面我们回顾了NIO编程,下面看看netty的各个组件是如何封装netty的,netty的主要组件包括:

    TransportChannel ----对应NIO中的channel

    EventLoop---- 对应于NIO中的while循环

    EventLoopGroup: 多个EventLoop,就是事件循环

    ChannelHandler和ChannelPipeline---对应于NIO中的客户逻辑实现handleRead/handleWrite(interceptor pattern)

    ByteBuf---- 对应于NIO 中的ByteBuffer

    Bootstrap 和 ServerBootstrap ---对应NIO中的Selector、ServerSocketChannel等的创建、配置、启动等

    上面的NIO提到过,把处理业务的方法抽象出来,对应的就是上面的ChannelHandler和ChannelPipeline组件,这里采用的是一个interceptor 模式,就是我们常用的设计模式中的拦截器模式,而整个的handler处理加起来就是一个责任链模式,我们在上面NIO中提到的接收,解码,编码,发送等,是一个双向的拦截器。而这整个流程加起来,放到了ChannelPipeline中,

    从上面的对应关系中,我们再次回顾NIO程序,可以找到我们对应的内容在netty中封装成了什么组件,那么这些组件如何使用呢?先看一下netty的主要流程:

    设置服务端ServerBootStrap启动参数

                1)group(boss,worker):
    
                2)channel(NioServerSocketChannel):设置通道类型
    
                3)handler():设置NioServerSocketChannel的ChannelHandlerPipeline
    
                4)childHandler():设置NioSocketChannel的ChannelHandlerPipeline
    

    通过ServerBootStrap的bind方法启动服务端,bind方法会在boss中注册NioServerScoketChannel,监听客户端的连接请求

                 1)会创建一个NioServerSocketChannel实例,并将其在boss中进行注册
    

    看完上面nio和netty的流程,我们来写一个netty小的例子,认识一下,首先添加一个依赖:

    file

    netty的服务端编程要从EventLoopGroup开始,我们要创建两个EventLoopGroup,一个是boss专门用来接收连接,可以理解为处理accept事件,另一个是worker,可以关注除了accept之外的其它事件,处理子任务。

    file

    上面注意,boss线程一般设置一个线程,设置多个也只会用到一个,而且多个目前没有应用场景(包括作者据说目前也没有找到。。。),worker线程通常要根据服务器调优,如果不写默认就是cpu的两倍。接下来服务端要启动,需要创建ServerBootStrap,在这里面netty把nio的模板式的代码都给封装好了:

    file

    下一步就是配置ServerBootStrap,

    file

    上面第一行配置了处理事件的线程,第二行配置了channel类型,第三行childHandler表示给worker那些线程配置了一个处理器,这个就是上面NIO中说的,把处理业务的具体逻辑抽象出来,放到Handler里面,如何处理一会再看。最后看看程序如何启动:

    file

    可以看到server绑定端口后直接启动,下面就是如何优雅的关闭了。服务端的启动代码很简单,比NIO少了很多。我们完整的看一次代码:

    file

    再看看channel的处理配置类:

    file

    这个就是把ServerHandler加到了channel的pipeline里面,看一下具体的ServerHandler:

    file

    ServerHandler集成了ChannelInboundHandlerAdapter,这是netty中的一个事件处理器,netty中的处理器分为Inbound(进站)和Outbound(出站)处理器,后面会详细介绍。

    上面的重定义了三个方法,channelRead方法表示读到消息以后如何处理,上面的处理方式就是把消息打印出来,ctx.write表示把消息再发送回客户端,但是仅仅是写到缓冲区,没有发送,flush才会真正写到网络上去。channelReadComplete方法表示消息读完了的处理,writeAndFlush方法表示写入并发送消息,这里的逻辑就是所有的消息读取完毕了,在统一写回到客户端。Unpooled.EMPTY_BUFFER表示空消息,addListener(ChannelFutureListener.CLOSE)表示写完后,就关闭连接。exceptionCaught方法就是发生异常的处理。

    可以看到handler处理的都是业务方法,基本看不到nio的影子了,逻辑上也很简单。现在我们直接启动netty服务端就可以看到效果:

    file

    Netty客户端编程

    netty服务端写完后,我们来看客户端,其实说完服务端以后,客户度很多组件也是类似的,事件循环客户度用的也是EventLoopGroup,而且客户端只是发起连接,不存在接收,所以使用一个EventLoopGroup就够了。服务端启动用的是ServerBootstrap,客户端用的就是Bootstrap。服务端的channel是NioServerSocketChannel,客户端的就是NioSocketChannel,我们来看一下代码:

    file

    基本上和服务端差不多,只不过更加简单。再来看一下客户端的消息处理器:

    file

    这里继承了一个SimpleChannelInboundHandler,和服务端的差别不大,这个Handler就是在消息不要的时候,可以把内存释放掉。再看上面的三个重写的方法,channelActive表示在通道在EventLoop上面注册完成,连接上服务器后调用,发送一个问候的消息。channelRead0方法会在read消息之后被调用,方法内的操作很简单,就是打印了一下从服务端接收到的内容。

    结合前面的服务端代码,客户端启动并连接到服务端后,会发送一个问候消息,服务端收到后就直接返回这个消息,这时候客户端会把服务端返回的消息打印在控制台上,然后关闭连接。这就是我们上面写的netty程序做的事件,虽然代码和类很陌生,但是熟悉了NIO后,流程其实很简单。

    下面启动客户端看一下效果:

    file

    看一下服务端的控制台内容:

    file

    基本上和我们计划的一样。通过这个例子,我们再来看netty执行的主要流程:

    Client发起连接CONNECT请求,boss中的NioEventLoop不断轮循是否有新的客户端请求,如果有,ACCEPT事件触发

    ACCEPT事件触发后,worker中NioEventLoop会通过NioServerSocketChannel获取到对应的代表客户端的NioSocketChannel,并将其注册到worker中

    worker中的NioEventLoop不断检测自己管理的NioSocketChannel是否有读写事件准备好,如果有的话,调用对应的ChannelHandler进行处理

    file

    上面这张图可以对着12345的顺序走一下,

    代码地址:https://gitee.com/blueses/netty-demo 05

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    转:页面Postback后定位滚动条不再难
    c:\windows\microsoft.net\framework\v1.1.4322\Config\machine.config 行: 198
    WebService相关概念和原理(中间层)
    JS 根据DropDownList的Text选中某一项
    javascript事件列表解说
    AJAXUpdateProgress设置CSS元素POSITION的使动画居中 & loading的Info
    ASP.NET2.0 Skin+CSS 测试
    C# 日期格式转换(转)
    编写代码创建DataTable对象
    ToString 格式化数值
  • 原文地址:https://www.cnblogs.com/guos/p/12188181.html
Copyright © 2020-2023  润新知