IO通信模型和Netty 下篇

本文深入探讨Netty框架的优势,包括其对IO模型的封装、数据格式处理及解决半包粘包问题的方法。通过实例展示了使用Netty简化网络编程的过程。

5、再次审视为什么使用Netty

上篇文章我们讨论了Netty的基本原理,重要概念,并使用java代码描述了Netty的基本使用。当然Netty的技术涵盖点远远不是那一篇基础代码就可以全部概括的,但是至少可以给读者一个切入点。让大家去思考一个我们一直在讨论的问题:为什么有了JAVA NIO框架后我们还需要有Netty这样的框架对底层再次进行封装?

5-1、IO模型的封装

5-1-1、再次总结IO模型

在前文中我们已经提到了,几种典型的IO模型(参见系统间通信3、4、5这三篇文章中的介绍,这里再进行一次总结):

  • 阻塞和非阻塞:这个概念是针对应用程序而言,是指应用程序中的线程在向操作系统发送IO请求后,是否一直等待操作系统的IO响应。如果是,那么就是阻塞式的;如果不是,那么应用程序一般会以轮询的方式以一定周期询问操作系统,直到某次获得了IO响应为止(轮序间隔应用程序线程可以做一些其他工作)。

  • 同步和异步:IO操作都是由操作系统进行的(这里的IO操作是个广泛概念了:磁盘IO、网络IO都算),不同的操作系统对不同设备的IO操作都有不同的模式。同步和异步这两个概念都指代的操作系统级别,同步IO是指操作系统和设备进行交互时,必须等待一次完整的请求-响应完成,才能进行下一次操作(当然操作系统和设备本身也有很多技术加快这个反应过程,例如“磁盘预读”技术、数据缓存技术);异步IO是指操作系统和设备进行交互时,不必等待本次得到响应,就可以直接进行下一次操作请求。设备处理完某次请求后,会主动给操作系统相应的响应通知

  • 多路复用IO:多路复用IO,从本质上看还是一种同步IO,因为它没有100%消除IO_WAIT,操作系统也没有为它提供“主动通知”机制。但是多路复用IO的处理速度已经相当快了,利用设备执行IO操作的时间,操作系统可以继续执行IO请求。并同样采用周期性轮询的方式,获取一批IO操作请求的执行响应。操作系统支持的多路复用IO技术主要有select、poll、epoll、kqueue。

  • 阻塞式同步IO模型:这个从字面上就很好理解了,应用程序请求IO操作,并一直等待处理结果;操作系统同时也进行IO操作,并等待设备的处理结果;可以看出,应用程序的请求线程和操作系统的内核线程都是等待状态。

  • 非阻塞式同步IO模型:应用程序请求IO,并且不用一直等待返回结果就去做其他事情。隔一定的周期,再去询问操作系统上次IO操作有没有结果,直到某一次询问从操作系统拿到IO结果;操作系统内核线程在进行IO操作时,还是处理一直等待设备返回操作结果的状态。

  • 非阻塞式多路复用IO模型:应用程序请求IO的工作采用非阻塞方式进行;操作系统采用多路复用模式工作。

  • 非阻塞式异步IO模型:应用程序请求IO的工作采用非阻塞方式进行,但是不需要轮询了,因为操作系统异步IO其中一个主要特性就是:可以在有IO响应结果的时候,主动进行通知

5-1-2、对IO模型的再次封装

以上这些IO工作模型,在JAVA中都能够找到对应的支持:传统的JAVA Socket套接字支持阻塞/非阻塞模式下的同步IO(有的技术资料里面也称为OIO或者BIO);JAVA NIO框架在不同操作系统下支持不同种类的多路复用IO技术(windows下的select模型、Linux下的poll/epoll模型);JAVA AIO框架支持异步IO(windows下的IOCP和Linux使用epoll的模拟AIO)

实际上Netty是对JAVA BIO 、JAVA NIO框架的再次封装。让我们不再纠结于选用哪种底层实现。您可以理解成Netty/MINA 框架是一个面向上层业务实现进行封装的“业务层”框架。而JAVA Socket框架、JAVA NIO框架、JAVA AIO框架更偏向于对下层技术实现的封装,是面向“技术层”的框架

5-2、数据信息格式的封装

“技术层”框架本身只对IO模型技术实现进行了封装,并不关心IO模型中流淌的数据格式;“业务层”框架对数据格式也进行了处理,让我们可以抽出精力关注业务本身。

  • Protobuf数据协议的集成:Netty利用自身的Channelpipeline的设计(在《架构设计:系统间通信(6)——IO通信模型和Netty 上篇》中讲过),对Protobuf数据协议进行了无缝结合。

  • JBoss Marshalling数据协议的集成:JBoss Marshalling 是一个Java对象的序列化API包,修正了JDK自带的序列化包的很多问题,又保持跟 java.io.Serializable 接口的兼容。Netty通过封装这个协议,可以帮助我们在客户端-服务端简便的进行对象系列化和反序列化。

  • HTTP Request / HTTP Response 协议的集成:在Netty中,可以方便的接受和发送Http协议。也就是说,我们可以使用Netty搭建自己的WEB服务器,当然您还可以根据自己的业务要求,方便的设计类似于Struts、Spring MVC这样的WEB框架。

下面是一个使用Netty的Http编码/解码处理器,设计的一个简单的WEB服务器:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">package testNetty<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

import java<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.net</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.InetSocketAddress</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import java<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.nio</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channels</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.spi</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SelectorProvider</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import java<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.util</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.concurrent</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ThreadFactory</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bootstrap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ServerBootstrap</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.buffer</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ByteBuf</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ChannelHandlerContext</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ChannelInboundHandlerAdapter</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ChannelInitializer</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ChannelOption</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.EventLoopGroup</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ChannelHandler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Sharable</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.nio</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NioEventLoopGroup</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.socket</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.nio</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NioServerSocketChannel</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.socket</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.nio</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.NioSocketChannel</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.DefaultFullHttpResponse</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.FullHttpResponse</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpContent</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpHeaders</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpMethod</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpRequest</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpRequestDecoder</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpResponseEncoder</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpResponseStatus</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.codec</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.http</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HttpVersion</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.util</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.AttributeKey</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.util</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.concurrent</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.DefaultThreadFactory</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

import org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commons</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.logging</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Log</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.commons</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.logging</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LogFactory</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import org<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.apache</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.log</span>4j<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.BasicConfigurator</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

public class TestHTTPNetty {
    static {
        BasicConfigurator<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.configure</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    }

    public static void main(String[] args) throws Exception {
        //这就是主要的服务启动器
        ServerBootstrap serverBootstrap = new ServerBootstrap()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //=======================下面我们设置线程池(代码已经详细讲解过,就不再赘述了)
        EventLoopGroup bossLoopGroup = new NioEventLoopGroup(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        ThreadFactory threadFactory = new DefaultThreadFactory(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"work thread pool"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        int processorsNumber = Runtime<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getRuntime</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.availableProcessors</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        EventLoopGroup workLoogGroup = new NioEventLoopGroup(processorsNumber * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, threadFactory, SelectorProvider<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.provider</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.group</span>(bossLoopGroup , workLoogGroup)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //========================下面我们设置我们服务的通道类型(代码已经详细讲解过,就不再赘述了)
        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span>(NioServerSocketChannel<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //========================设置处理器
        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.childHandler</span>(new ChannelInitializer<NioSocketChannel>() {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* (non-Javadoc)
             * @see io.netty.channel.ChannelInitializer#initChannel(io.netty.channel.Channel)
             */</span>
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                //我们在socket channel pipeline中加入http的编码和解码器
                ch<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.pipeline</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addLast</span>(new HttpResponseEncoder())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                ch<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.pipeline</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addLast</span>(new HttpRequestDecoder())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                ch<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.pipeline</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addLast</span>(new HTTPServerHandler())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            }
        })<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.option</span>(ChannelOption<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SO</span>_BACKLOG, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.childOption</span>(ChannelOption<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SO</span>_KEEPALIVE, true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        serverBootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bind</span>(new InetSocketAddress(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"0.0.0.0"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">83</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    }
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * @author yinwenjie
 */</span>
@Sharable
class HTTPServerHandler extends ChannelInboundHandlerAdapter {
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 日志
     */</span>
    private static Log LOGGER = LogFactory<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getLog</span>(HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 由于一次httpcontent可能没有传输完全部的请求信息。所以这里要做一个连续的记录
     * 然后在channelReadComplete方法中(执行了这个方法说明这次所有的http内容都传输完了)进行处理
     */</span>
    private static AttributeKey<StringBuffer> CONNTENT = AttributeKey<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.valueOf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"content"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* (non-Javadoc)
     * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object)
     */</span>
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 在测试中,我们首先取出客户端传来的参数、URL信息,并且返回给一个确认信息。
         * 要使用HTTP服务,我们首先要了解Netty中http的格式,如下:
         * ----------------------------------------------
         * | http request | http content | http content |
         * ----------------------------------------------
         * 
         * 所以通过HttpRequestDecoder channel handler解码后的msg可能是两种类型:
         * HttpRquest:里面包含了请求head、请求的url等信息
         * HttpContent:请求的主体内容
         * */</span>
        if(msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest)msg<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            HttpMethod method = request<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getMethod</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

            String methodName = method<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.name</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            String url = request<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getUri</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LOGGER</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.info</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"methodName = "</span> + methodName + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" && url = "</span> + url)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        } 

        //如果条件成立,则在这个代码段实现http请求内容的累加
        if(msg instanceof HttpContent) {
            StringBuffer content = ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.attr</span>(HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONNTENT</span>)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            if(content == null) {
                content = new StringBuffer()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.attr</span>(HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONNTENT</span>)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.set</span>(content)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            }

            HttpContent httpContent = (HttpContent)msg<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            ByteBuf contentBuf = httpContent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.content</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            String preContent = contentBuf<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.toString</span>(io<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.netty</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.util</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CharsetUtil</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.UTF</span>_8)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
            content<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.append</span>(preContent)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        }
    } 

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* (non-Javadoc)
     * @see io.netty.channel.ChannelInboundHandlerAdapter#channelReadComplete(io.netty.channel.ChannelHandlerContext)
     */</span>
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LOGGER</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.info</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"super.channelReadComplete(ChannelHandlerContext ctx)"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
         * 一旦本次http请求传输完成,则可以进行业务处理了。
         * 并且返回响应
         * */</span>
        StringBuffer content = ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.attr</span>(HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONNTENT</span>)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.get</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        HTTPServerHandler<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LOGGER</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.info</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http客户端传来的信息为:"</span> + content)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //开始返回信息了
        String returnValue = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"return response"</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.HTTP</span>_1_1, HttpResponseStatus<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.OK</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        HttpHeaders httpHeaders = response<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.headers</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        //这些就是http response 的head信息咯,参见http规范。另外您还可以设置自己的head属性
        httpHeaders<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"param"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"value"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        response<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.headers</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.set</span>(HttpHeaders<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Names</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONTENT</span>_TYPE, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"text/plain"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        //一定要设置长度,否则http客户端会一直等待(因为返回的信息长度客户端不知道)
        response<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.headers</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.set</span>(HttpHeaders<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Names</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CONTENT</span>_LENGTH, returnValue<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.length</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        ByteBuf responseContent = response<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.content</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        responseContent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.writeBytes</span>(returnValue<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getBytes</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //开始返回
        ctx<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.writeAndFlush</span>(response)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    } 
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li></ul>

由于上篇文章中已经介绍了Netty的基本使用方法,所以以上的代码将其他不必要的注释、方法都去掉了,只做了实现web服务器的最简代码。但是这段代码本省是可以运行的。下面是运行效果:

这里写图片描述

5-3、解决了“技术层”框架中的技术问题

通过阅读Netty框架的代码,我们知道了Netty框架至少解决了JAVA NIO框架中的一些Bug:

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">sun<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>nio<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>ch<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>Util contains code which is <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">thread</span> safe <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">and</span> can throw a NullPointerException:
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> static <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span>;

    static boolean atBugLevel(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> bl) {      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// package-private</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">==</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!</span>sun<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>misc<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>VM<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>isBooted())
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">false</span>;
            java<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>security<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>PrivilegedAction pa <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span>
                <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">new</span> GetPropertyAction(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"sun.nio.ch.bugLevel"</span>);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// the next line can reset bugLevel to null</span>
            bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>)AccessController<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>doPrivileged(pa);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">==</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span>)
                bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (bugLevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span>) <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">&&</span> bugLevel<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">equals</span>(bl);
    }

Suppose that two threads enter the <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"if (buglevel == null)"</span> body at the same time<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span> The first one runs until the <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> line <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">and</span> gets scheduled out right after the (buglevel <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">!=</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span>) check<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span> The second one then runs until right after the doPrivileged() call, sets bugLevel <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">and</span> gets scheduled out<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span> The first one continues <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">and</span> hits a NullPointerException <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> calling bugLevel<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">equals</span>() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> bugLevel being <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">null</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

这个问题在Netty框架中,负责进行JAVA NIO Selector的NioEventLoop类中得到了解决。

  • workaround the infamous epoll 100% CPU bug。http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6403933。这个Bug出现在linux系统环境,大致是说JAVA NIO 框架在实现 Linux内核 kernel 2.6+中的epoll模型时。Selector.select(timeout)方法不能阻塞指定的timeout时间,导致CPU 100%的情况:
<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">A DESCRIPTION OF THE PROBLEM :
Trying <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">get</span> all bindings <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> transient nameserver brings orbd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> state where <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> consumes <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>% CPU. Its interesting <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> note that <span class="hljs-operator" style="box-sizing: border-box;">the</span> problem only occurs <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-operator" style="box-sizing: border-box;">the</span> client is programmed <span class="hljs-operator" style="box-sizing: border-box;">in</span> c++. I was <span class="hljs-operator" style="box-sizing: border-box;">not</span> able <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> reproduce <span class="hljs-operator" style="box-sizing: border-box;">the</span> problem <span class="hljs-operator" style="box-sizing: border-box;">with</span> <span class="hljs-operator" style="box-sizing: border-box;">a</span> client programmed <span class="hljs-operator" style="box-sizing: border-box;">in</span> Java.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) Get omniORB <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.1</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">http</span>://omniorb.sourceforge.net

<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) Compile omniORB (requires python devel package installed)
cd /tmp
mkdir omni_local
tar xvzf omniORB-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.0</span>.tar.gz
cd omniORB-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4.1</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">.0</span>
./configure <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--prefix=/tmp/omni_local</span>
make
make install

<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>) Compile <span class="hljs-operator" style="box-sizing: border-box;">the</span> test program (binding_browser, source attached <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">to</span> this report)
g++ -I/tmp/omni_local/<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">include</span> -L/tmp/omni_local/lib -lomniORB4 -lomniDynamic4 -lomnithread -lpthread -lrt BindingBrowser.cc -o binding_browser

<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>) Start orbd
<JAVA_HOME>/bin/orbd -ORBInitialPort <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12345</span>

<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>) Start binding_browser (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">from</span> another <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">shell</span>)
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span><span class="hljs-operator" style="box-sizing: border-box;">a</span>) export LD_LIBRARY_PATH=/tmp/omni_local/lib:$LD_LIBRARY_PATH
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>b) ./binding_browser -ORBInitRef NameService=corbaloc::<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.2</span>@localhost:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12345</span>/TNameService

Repeat step <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>b <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">until</span> orbd consumes <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>% cpu.</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

这个问题从官方的Bug Database中的描述看,是在JDK7的版本中被解决的。Netty框架在JDK 6+的环境下在JAVA NIO框架封装之上解决了这个Bug。

5-4、半包和粘包问题

我们考虑一下这样的情况:我们编写了一个机器人控制程序,通过一个遥控器(客户端)向机器人(服务器)建立了一个长连接,并通过这个连接连续不断的从遥控器发送控制指令给机器人。由于是连续控制指令,所以指令与指令之间没有间隔(实际上您还可以想想很多类似场景,例如:开发的Online对战游戏)。

我们使用JSON格式作为指令数据的承载格式。那么发送方和接收方的数据发送-接受过程可能如下图所示。

这里写图片描述

通过上图我们看到了接收方为了接受这两条连贯的指令,一共做了三次接受,第二次接收的时候,收到了一部分message1的内容和一部分message2的内容。这里要说明几个注意事项:

  • MSS:MSS属性是TCP连接双方在三次握手时所确认的每一个TCP报文段中数据字段的最大长度。注意,一是连接双方协商出来的;二是只是数据段的最大长度,不包括IP协议头和TCP协议头的最大长度。

  • 半包是指接收方应用程序在接收信息时,没有接收到一个完成的信息格式块;粘包是指,接收方应用程序在接受信息时,除了接收到发送方应用程序发送的某一个完整数据信息描述外,还接受到了一下发送方应用程序发送的下一个数据信息的一部分。

  • 半包和粘包是针对应用程序来说的,这个问题只会发生在TCP一些进行连续发送数据时(TCP长连接)。UDP不会出现这个问题,因为UDP都是有边界的数据报;TCP短连接也不会出现,因为发送完一个指令信息后连接就断开了,不会发送第二个指令数据。

  • 半包和粘包问题产生的根本是因为TCP本质上没有“数据块”的概念,而是一连串的数据流。在应用程序层面上我们所定义的“数据块”在TCP层面上并不被协议认可

  • 半包/粘包是一个应用层问题。要解决半包/粘包问题,就是在应用程序层面建立协商一致的信息还原依据。常见的有两种方式:一是消息定长,即保证每一个完整的信息描述的长度都是一定的,这样无论TCP/IP协议如何进行分片,数据接收方都可以按照固定长度进行消息的还原。二是在完整的一块数据结束后增加协商一致的分隔符(例如增加一个回车符)。

在JAVA NIO技术框架中,半包和粘包问题我们需要自己解决,如果使用Netty框架,它其中提供了多种解码器的封装帮助我们解决半包和粘包问题。甚至针对不同的数据格式,Netty都提供了半包和粘包问题的现成解决方式,例如之前我们提到的ProtobufVarint32FrameDecoder解码器,就是专门解决Protobuf数据格式在TCP长连接传输时的半包问题的。

下文中我们会介绍FixedLengthFrameDecoder、DelimiterBasedFrameDecoder、LineBasedFrameDecoder来解决半包/粘包的问题。

由于上文中我们已经通过完整的代码演示了Netty的基本使用,所以下面的示例代码中为了节约篇幅,我只会列出重要的代码片段。

5-4-1、使用FixedLengthFrameDecoder解决问题

FixedLengthFrameDecoder解码处理器将TCP/IP的数据按照指定的长度进行重新拆分,如果接收到的数据不满足设置的固定长度,Netty将等待新的数据到达:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">serverBootstrap.childHandler(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ChannelInitializer<NioSocketChannel>() {
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initChannel</span>(NioSocketChannel ch) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayEncoder());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> FixedLengthFrameDecoder(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>));
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TCPServerHandler());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayDecoder());
    }
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

Netty上层的channelRead事件方法将在Channel接收到20个字符的情况下被触发;而如果剩余的内容不到20个字符,channelRead方法将不会被触发(但注意channelReadComplete方法会触发的啦)。

5-4-2、使用LineBasedFrameDecoder解决问题

LineBasedFrameDecoder解码器,基于最简单的“换行符”进行接收到的信息的再组织。windows和linux两个操作系统中的“换行符”是不一样的,LineBasedFrameDecoder解码器都支持。当然这个解码器没有我们后面介绍的DelimiterBasedFrameDecoder解码器灵活。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">serverBootstrap.childHandler(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ChannelInitializer<NioSocketChannel>() {
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initChannel</span>(NioSocketChannel ch) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayEncoder());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LineBasedFrameDecoder(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>));
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TCPServerHandler());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayDecoder());
    }
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

那么如果客户端发送的数据是:

this is 0 client \r\n request 1 \r\n”

那么接收方重新通过“换行符”重新组织后,将分两次接受到数据:

this is 0 client 
request 1

5-4-3、使用DelimiterBasedFrameDecoder解决问题

DelimiterBasedFrameDecoder是按照“自定义”分隔符(也可以是“回车符”或者“空字符”注意windows系统中和linux系统中“回车符”的表示是不一样的)进行信息的重新拆分。

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">serverBootstrap.childHandler(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ChannelInitializer<NioSocketChannel>() {
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initChannel</span>(NioSocketChannel ch) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayEncoder());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DelimiterBasedFrameDecoder(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1500</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>, Delimiters.lineDelimiter()));
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TCPServerHandler());
        ch.pipeline().addLast(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ByteArrayDecoder());
    }
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

DelimiterBasedFrameDecoder有三个参数,这里介绍一下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">DelimiterBasedFrameDecoder(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> maxFrameLength, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> stripDelimiter, ByteBuf... delimiters)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
  • maxFrameLength:最大分割长度,如果接收方在一段长度 大于maxFrameLength的数据段中,没有找到指定的分隔符,那么这个处理器会抛出TooLongFrameException异常。

  • stripDelimiter:这个是一个布尔型参数,指代是否保留指定的分隔符。

  • delimiters:设置的分隔符。一般使用Delimiters.lineDelimiter()或者Delimiters.nulDelimiter()。当然您也可以自定义分隔符,定义成bytebuf的类型就行了。

5-5、专注于业务

Netty框架的特性,使我们不需要关心下层所工作的IO模型,利用Netty提供的面向事件驱动的方法结构,使我们更能集中精力关注应用层业务。

在这5篇文章中,我们重点介绍了几种典型的IO模型,并且介绍了JAVA语言对这几种IO模型的实现,最后我们简单介绍了一下Netty框架,并且比较了JAVA NIO框架和Netty框架侧重点。实际上这几篇文章我们讲述的问题只有一个“信息如何进行传递”。

从下一篇文章开始,我们开始介绍JAVA RMI技术,并从JAVA RMI技术引出一项系统间通信重要的技术RPC,我们还会降到RPC的重要实现 TaoBao-Dubbo框架,最后我们讲解ESB技术和几个典型的ESB实现。这些技术要解决的问题是“传递过程如果进行统筹管理”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值