netty组件---ChannelHandler

ChannelHandler 接口
从应用程序开发人员的角度来看, Netty 的主要组件是 ChannelHandler, 它充当了所有
处理入站和出站数据的应用程序逻辑的容器。 ChannelHandler 的方法是由网络事件触发的。
事实上, ChannelHandler 可专门用于几乎任何类型的动作, 例如将数据从一种格式转换为另
外一种格式, 例如各种编解码, 或者处理转换过程中所抛出的异常。
举例来说, ChannelInboundHandler 是一个你将会经常实现的子接口。 这种类型的
ChannelHandler 接收入站事件和数据, 这些数据随后将会被你的应用程序的业务逻辑所处理。
当你要给连接的客户端发送响应时, 也可以从 ChannelInboundHandler 直接冲刷数据然后输
出到对端。 应用程序的业务逻辑通常实现在一个或者多个 ChannelInboundHandler 中。
这种类型的 ChannelHandler 接收入站事件和数据, 这些数据随后将会被应用程序的业
务逻辑所处理。
Netty 定义了下面两个重要的 ChannelHandler 子接口:
ChannelInboundHandler——处理入站数据以及各种状态变化;
ChannelOutboundHandler——处理出站数据并且允许拦截所有的操作。
ChannelInboundHandler 接口
下面列出了接口 ChannelInboundHandler 的生命周期方法。 这些方法将会在数据被接收
时或者与其对应的 Channel 状态发生改变时被调用。 正如我们前面所提到的, 这些方法和
Channel 的生命周期密切相关。
channelRegistered 当 Channel 已经注册到它的 EventLoop 并且能够处理 I/O 时被调用
channelUnregistered 当 Channel 从它的 EventLoop 注销并且无法处理任何 I/O 时被调

channelActive 当 Channel 处于活动状态时被调用; Channel 已经连接/绑定并且已经就

channelInactive 当 Channel 离开活动状态并且不再连接它的远程节点时被调用
channelReadComplete 当 Channel 上的一个读操作完成时被调用
channelRead 当从 Channel 读取数据时被调用
ChannelWritabilityChanged
当 Channel 的可写状态发生改变时被调用。 可以通过调用 Channel 的 isWritable()方法
来检测 Channel 的可写性。 与可写性相关的阈值可以通过
Channel.config().setWriteHighWaterMark()和 Channel.config().setWriteLowWaterMark()方法来
设置
userEventTriggered 当 ChannelnboundHandler.fireUserEventTriggered()方法被调用时被
调用。
ChannelOutboundHandler 接口
出站操作和数据将由 ChannelOutboundHandler 处理。 它的方法将被 Channel、 ChannelPipeline 以及 ChannelHandlerContext 调用。
所有由 ChannelOutboundHandler 本身所定义的方法:
bind(ChannelHandlerContext,SocketAddress,ChannelPromise)
当请求将 Channel 绑定到本地地址时被调用
connect(ChannelHandlerContext,SocketAddress,SocketAddress,ChannelPromise)
当请求将 Channel 连接到远程节点时被调用
disconnect(ChannelHandlerContext,ChannelPromise)
当请求将 Channel 从远程节点断开时被调用
close(ChannelHandlerContext,ChannelPromise) 当请求关闭 Channel 时被调用
deregister(ChannelHandlerContext,ChannelPromise)
当请求将 Channel 从它的 EventLoop 注销时被调用
read(ChannelHandlerContext) 当请求从 Channel 读取更多的数据时被调用
flush(ChannelHandlerContext) 当请求通过 Channel 将入队数据冲刷到远程节点时被调

write(ChannelHandlerContext,Object,ChannelPromise) 当请求通过 Channel 将数据写到
远程节点时被调用
ChannelHandler 的适配器
有一些适配器类可以将编写自定义的 ChannelHandler 所需要的工作降到最低限度, 因
为它们提供了定义在对应接口中的所有方法的默认实现。 因为你有时会忽略那些不感兴趣的
事件, 所以 Netty 提供了抽象基类 ChannelInboundHandlerAdapter 和
ChannelOutboundHandlerAdapter。
你可以使用 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 类作为
自己的 ChannelHandler 的起始点。 这两个适配器分别提供了 ChannelInboundHandler 和
ChannelOutboundHandler 的基本实现。 通过扩展抽象类 ChannelHandlerAdapter, 它们获得
了它们共同的超接口 ChannelHandler 的方法。
ChannelHandlerAdapter 还提供了实用方法 isSharable()。 如果其对应的实现被标注为
Sharable, 那么这个方法将返回 true, 表示它可以被添加到多个 ChannelPipeline。

资源管理和 SimpleChannelInboundHandler
回想一下我们在 NIO 中是如何接收和发送网络数据的? 都是首先创建了一个 Buffer, 应
用程序中的业务部分和 Channel 之间通过 Buffer 进行数据的交换:

Netty 在处理网络数据时, 同样也需要 Buffer, 在 Read 网络数据时由 Netty 创建 Buffer,
Write 网络数据时 Buffer 往往是由业务方创建的。 不管是读和写, Buffer 用完后都必须进行
释放, 否则可能会造成内存泄露。
在 Write 网络数据时, 可以确保数据被写往网络了, Netty 会自动进行 Buffer 的释放,
但是如果 Write 网络数据时, 我们有 outBoundHandler 处理了 write()操作并丢弃了数据, 没
有继续往下写, 要由我们负责释放这个 Buffer, 就必须调用 ReferenceCountUtil.release 方法,
否则就可能会造成内存泄露。
在 Read 网络数据时, 如果我们可以确保每个 InboundHandler 都把数据往后传递了, 也
就是调用了相关的 fireChannelRead 方法, Netty 也会帮我们释放, 同样的, 如果我们有
InboundHandler 处理了数据, 又不继续往后传递, 又不调用负责释放的
ReferenceCountUtil.release 方法, 就可能会造成内存泄露。
但是由于消费入站数据是一项常规任务, 所以 Netty 提供了一个特殊的被
称为 SimpleChannelInboundHandler 的 ChannelInboundHandler 实现。 这个实现会在数
据被 channelRead0()方法消费之后自动释放数据

同时系统为我们提供的各种预定义 Handler 实现, 都实现了数据的正确处理, 所以我们
自行在编写业务 Handler 时, 也需要注意这一点: 要么继续传递, 要么自行释放。
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值