龙空技术网

「Netty核心技术」6-ChannelPipeline源码

逆向投资 233

前言:

现时看官们对“nettypipeline怎么用”都比较关切,看官们都想要知道一些“nettypipeline怎么用”的相关文章。那么小编也在网络上汇集了一些关于“nettypipeline怎么用””的相关文章,希望大家能喜欢,兄弟们快快来学习一下吧!

ChannelPipeline是Channelhandler的容器,它负责ChannelHandler的管理和事件拦截与调度。

土话:

ChannelPipeline就是用来管理Channelhandler有增删功能。还有一些事件的拦截,交给ChannelHandler处理。

关于阅读源码的步骤,请参考这份源码阅读步骤你值得拥有

ChannelPipeline的功能

管理ChannelHandler

addXXX:增加ChannelHandlerget:获得ChannelHandlerremove:移除ChannelHandlerreplace:代替ChannelHander

拦截ChannelHandler的事件,这里比较重要

从图中看

从Socket.read()经过ChannelHandler1,ChannelHandler2....ChannelHandlerN开始称为inbound事件。从ChannelHandlerContext开始经过ChannelHandlerN,ChannelHandlerN-1,...一直到ChannelHandler1,Socket.write()称为outbound事件。

inbound事件对应ChannelInboundInvoker类

inbound事件通常由I/O线程触发,例如TCP链路建立事件,链路关闭事件,读事件,异常通知事件等。

public interface ChannelInboundInvoker {    //Channel注册事件    //Channel注册成功后会执行该方法,对应的地方AbstractChannel.register0方法    ChannelInboundInvoker fireChannelRegistered();    //取消注册事件    //取消注册后调用,对应的地方AbstractChannel.deregister    ChannelInboundInvoker fireChannelUnregistered();    //TCP链路建立成功,Channel激活事件,客户端与服务端建立连接    //客户端发起请求后    //服务端会从ServerBootstrapAcceptor会收到channelRead,childGroup注册一个child    //对应的地方是AbstractChannel.register0    //客户端则再连接成功后对应的地方AbstractNioChannel.fulfillConnectPromise    ChannelInboundInvoker fireChannelActive();    //客户端与服务端断开连接的时候调用    ChannelInboundInvoker fireChannelInactive();    //异常的通知事件    ChannelInboundInvoker fireExceptionCaught(Throwable cause);    //用户自定义事件    //就是我们定义ChannelHandler的时候可以调用我们自定义的fireUserEventTriggered    ChannelInboundInvoker fireUserEventTriggered(Object event);    //读数据事件    //对应调用的地方是NioUnsafe.read    ChannelInboundInvoker fireChannelRead(Object msg);        //读操作完成    //对应调用的地方是NioUnsafe.read读完后调用    ChannelInboundInvoker fireChannelReadComplete();    //channel的可写状态变化通知事件    ChannelInboundInvoker fireChannelWritabilityChanged();}

上面的每个方法都很重要,我们要自定义ChannelHandler的时候必须要知道怎么调用这些方法。

outbound事件对应ChannelOutboundInvoker类

outbound通常是由用户主动发起的网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。

public interface ChannelOutboundInvoker {    //bind本地地址事件    ChannelFuture bind(SocketAddress localAddress);    //连接服务端事件    ChannelFuture connect(SocketAddress remoteAddress);        ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);    //断开连接事件    ChannelFuture disconnect();    //关闭当前channel事件    ChannelFuture close();        //取消注册事件    ChannelFuture deregister();    ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);    ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);    ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);    ChannelFuture disconnect(ChannelPromise promise);    ChannelFuture close(ChannelPromise promise);    ChannelFuture deregister(ChannelPromise promise);        //读事件    ChannelOutboundInvoker read();        //发送事件    ChannelFuture write(Object msg);       ChannelFuture write(Object msg, ChannelPromise promise);    	//刷新事件    ChannelOutboundInvoker flush();        //写和刷新事件    ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);    ChannelFuture writeAndFlush(Object msg);     ChannelPromise newPromise();       ChannelProgressivePromise newProgressivePromise();    ChannelFuture newSucceededFuture();    ChannelFuture newFailedFuture(Throwable cause);     ChannelPromise voidPromise();}

我们扩展事件一般是在inbound事件。

核心类DefaultChannelPipeline

DefaultChannelPipeline是Netty用来管理ChannelHandler的核心类

DefaultChannelPipeline

protected DefaultChannelPipeline(Channel channel) {    this.channel = ObjectUtil.checkNotNull(channel, "channel");    succeededFuture = new SucceededChannelFuture(channel, null);    voidPromise =  new VoidChannelPromise(channel, true);    tail = new TailContext(this);    head = new HeadContext(this);    head.next = tail;    tail.prev = head;}

分析DefaultChannelPipeline关键成员变量

head:是现实HeadContext继承了AbstractChannelHandlerContext,AbstractChannelHandlerContext就是Channelhandler的上下文。DefaultChannelPipeline包含了很多ChannelHander,指向第一个事件tail:对应TailContext,指向DefaultChannelPipeline的末尾事件。channel:注册的channel,例如服务端对应的就是NioSockerServerChannel,客户端对应的就是NioSocketChannel。pendingHandlerCallbackHead:当执行完了handler的增加删除操作后调用,用来做回调处理。registered:AbstractChannel是否注册,一旦注册了就不会再改变了

分析AbstractChannelHandlerContext类

AttributeMap,DefaultAttributeMap一些参数的定义MapResourceLeakHint:就是用来定义做一些提示,打印一些自定义参数用的。ChannelHandlerContext:它代表了 ChannelHandler 和ChannelPipeline 之间的关联。接口ChannelHandlerContext 主要是对通过同一个 ChannelPipeline 关联的 ChannelHandler 之间的交互进行管理。

ChannelHandlerContext就是结合了ChannelInboundInvoker和ChannelOutboundInvoker,然后多了一些Handler的处理,比如说名称,获得ChannelHandler等等。

阅读源码知识点:

刚开始设计框架的时候,开发者也不会说设计的很完善,都是后面设计之后,慢慢抽象出来的。例如你要问我为什么要设计一个ChannelHandlerContext出来,我只能跟你说,有一些抽象方法ChannelInboundInvoker和ChannelOutboundInvoker没有必须要有一个新的接口聚合它两,并且要提供一些方法。

再来看AbstractChannelHandlerContext成员变量

AbstractChannelHandlerContext next:头结点AbstractChannelHandlerContext prev:尾结点inBound:是否为inbound事件outbound:是否为outbound事件

AbstractChannelHandlerContext的结构是一个双链表

AbstractChannelHandlerContext结构

再来分析DefaultChannelHandlerContext类

final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {    private final ChannelHandler handler;    DefaultChannelHandlerContext(            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {        super(pipeline, executor, name, isInbound(handler), isOutbound(handler));        if (handler == null) {            throw new NullPointerException("handler");        }        this.handler = handler;    }

主要就是封装handler成一个Context

分析HeadContext类

 final class HeadContext extends AbstractChannelHandlerContext            implements ChannelOutboundHandler, ChannelInboundHandler

HeadContext实现了ChannelOutboundHandler,ChannelInboundHandler。上面说过outbound事件是一些网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。intbound:CP链路建立事件,链路关闭事件,读事件,异常通知事件等。

分析TailContext类

final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler

TailContext只实现了ChannelInboundHandler,但是它的一些inbound事件都不能使用,因为HeadContext已经使用了。

 @Override        public void channelActive(ChannelHandlerContext ctx) throws Exception {            onUnhandledInboundChannelActive();        }        @Override        public void channelInactive(ChannelHandlerContext ctx) throws Exception {            onUnhandledInboundChannelInactive();        }        @Override        public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {            onUnhandledChannelWritabilityChanged();        }

onUnhandledXXXX:就表示do noting。

小结一下,本篇讲解了

ChannelPipeline的功能,是用来管理Channelhandler,和拦截事件请求。分析了ChannelPipeline的inbound事件通常由I/O线程触发,例如TCP链路建立事件,链路关闭事件,读事件,异常通知事件等。outbound通常是由用户主动发起的网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。核心类DefaultChannelPipeline的功能核心类DefaultChannelPipeline的成员变量AbstractChannelHandlerContext是一个双向链表,它用来保存Channelhandler核心类DefaultChannelPipeline的成员变量,HeadContext指向AbstractChannelHandlerContext的头部,TailContext指向AbstractChannelHandlerContext尾部。

下篇讲解ChannelPipeline源码解析二,主要分析DefaultChannelPipeline中的核心方法。

建议阅读

「Netty核心技术」5-客户端启动

「Netty核心技术」4-服务端启动

「Netty核心技术」3-AbstractBootStrap

「Netty核心技术」2-HelloWorld

「Netty核心技术」1-序言

标签: #nettypipeline怎么用