Netty学习笔记(六)ChannelHandler和ChannelPipeLine

一、ChannelHandler

1、Channel生命周期

Channel 定义了一组和 ChannelInboundHandler API 密切相关的简单但功能强大的状态模型,下表展示的是Channel的生命周期个阶段状态:

状态 描述

ChannelUnregistered 

Channel 已经被创建,但还未注册到 EventLoop 

ChannelRegistered 

Channel 已经被注册到了 EventLoop 

ChannelActive 

Channel 处于活动状态(已经连接到它的远程节点)。它现在可以接收和发送数据了 

ChannelInactive 

Channel没有连接到远程节点 

Channel 的正常生命周期如下图所示。当这些状态发生改变时,将会生成对应的事件。 这些事件将会被转发给 ChannelPipeline 中的 ChannelHandler,其可以随后对它们做出响应。 

 2、ChannelHandler的生命周期

下表列出了 ChannelHandler 定义的生命周期操作,在 ChannelHandler 被添加到 ChannelPipeline 中或者被从 ChannelPipeline 中移除时会调用这些操作。这些方法中的每一个都接受一个 ChannelHandlerContext 参数。 

类型 描述

handlerAdded 

当把 ChannelHandler 添加到 ChannelPipeline 中时被调用 

handlerRemoved 

当从 ChannelPipeline 中移除 ChannelHandler 时被调用 

exceptionCaught 

当处理过程中在 ChannelPipeline 中有错误产生时被调用 

3、ChannelHandler接口

Netty 定义了下面两个重要的 ChannelHandler 子接口:

ChannelInboundHandler:处理入站数据以及各种状态变化;

ChannelOutboundHandler:处理出站数据并且允许拦截所有的操作。

不仅如此,我们也可以使用 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 类作为自己的 ChannelHandler 的起始点。这两个适配器分别提供了 ChannelInboundHandler 和 ChannelOutboundHandler 的基本实现。通过扩展抽象类 ChannelHandlerAdapter,它们获得了它们共同的超接口ChannelHandler 的方法。 他们的类关系图如下:

二、ChannelPipeLine

ChannelPipeline 就是一个拦截流经 Channel 的入站和出站事件的 ChannelHandler 实例链,每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline。这项关联是永久性的,Channel 既不能附加另外一个 ChannelPipeline,也不能分离其当前的。根据事件的起源,事件将会被 ChannelInboundHandler 或者 ChannelOutboundHandler处理,随后,通过调用 ChannelHandlerContext 实现,它将被转发给同一超类型的下一个ChannelHandler。 

下图展示了一个典型的同时具有入站和出站 ChannelHandler 的 ChannelPipeline 的布局,如果一个入站事件被触发,它将被从 ChannelPipeline 的头部开始一直被传播到 ChannelPipeline 的尾端。 而一个出站事件将从 ChannelPipeline 的尾端开始传递到头部。 

1、修改ChannelPipeLine

ChannelHandler 可以通过添加、删除或者替换其他的 ChannelHandler 来实时地修改 ChannelPipeline 的布局。(它也可以将它自己从 ChannelPipeline 中移除。)下表列出了相关方法:

方法 说明

addFirst

addLast

addBefore

addAfter

将一个ChannelHandler添加到ChannelPipeline中 

remove

将一个 ChannelHandler 从 ChannelPipeline 中移除

replace 

将 ChannelPipeline 中的一个 ChannelHandler 替换为另一个 ChannelHandler 

除了这些操作,还有别的通过类型或者名称来访问 ChannelHandler 的方法如下表所示

方法 说明
get

通过类型或者名称返回 ChannelHandler

context

返回和 ChannelHandler 绑定的 ChannelHandlerContext 

names

返回 ChannelPipeline 中所有 ChannelHandler 的名称 

2、触发事件

ChannelPipeline 的API公开了用于调用入站和出站操作的附加方法。下表列出了入站操作,用于通知 ChannelInboundHandler 在 ChannelPipeline 中所发生的事件。

方法 说明

fireChannelRegistered 

 调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelRegistered(ChannelHandlerContext)方法 

fireChannelUnregistered 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelUnregistered(ChannelHandlerContext)方法 

fireChannelActive 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelActive(ChannelHandlerContext)方法 

fireChannelInactive 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelInactive(ChannelHandlerContext)方法 

fireExceptionCaught 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 exceptionCaught(ChannelHandlerContext, Throwable)方法 

fireUserEventTriggered 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 userEventTriggered(ChannelHandlerContext, Object)方法 

fireChannelRead

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelRead(ChannelHandlerContext, Object msg)方法 

fireChannelReadComplete 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelReadComplete(ChannelHandlerContext)方法 

fireChannelWritabilityChanged 

调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelWritabilityChanged(ChannelHandlerContext)方法 

下表列出了ChannelPipeline API 的出站操作:

方法 说明
bind 将 Channel 绑定到一个本地地址,这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的bind(ChannelHandlerContext, SocketAddress, ChannelPromise)方法 
connect 将 Channel 连接到一个远程地址,这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 connect(ChannelHandlerContext, SocketAddress, ChannelPromise)方法
disconnect 将 Channel 断开连接。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 disconnect(ChannelHandlerContext, Channel Promise)方法 
close 将 Channel 关闭。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 close(ChannelHandlerContext, ChannelPromise)方法

deregister

将 Channel 从它先前所分配的 EventExecutor(即 EventLoop)中注销。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 deregister (ChannelHandlerContext, ChannelPromise)方法 
 flush 冲刷 Channel 所有挂起的写入。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 flush(ChannelHandlerContext)方法 
write  将消息写入 Channel。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 write(ChannelHandlerContext, Object msg, ChannelPromise)方法。注意:这并不会将消息写入底层的 Socket,而只会将它放入队列中。 要将它写入 Socket,需要调用 flush()或者 writeAndFlush()方法 
writeAndFlush  这是一个先调用write()方法再接着调用flush()方法的便利方法
read  请求从 Channel 中读取更多的数据。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 read(ChannelHandlerContext)方法 

总结一下:

  • ChannelPipeline 保存了与 Channel 相关联的 ChannelHandler;
  • ChannelPipeline 可以根据需要,通过添加或者删除 ChannelHandler 来动态地修改;
  • ChannelPipeline 有着丰富的 API 用以被调用,以响应入站和出站事件。  
posted @ 2020-06-29 17:46  阿拉懒神灯  阅读(119)  评论(0)    收藏  举报