Netty入门(五)ChanneHandler
本节主要讨论了 Netty 的数据处理组件 ChannelHandler。
一、Channel 生命周期
Channel 有个简单但强大的状态模型,下面是 Channel 的四个状态:

Channel 的正常生命周期如下图,当这些状态发生变化时,对应的事件将会生成。

二、ChannelHandler 生命周期
ChannelHandler 定义的生命周期如下,当 ChannelHandler 添加到 ChannelPipeline,或者从 ChannelPipeline 移除后,这些将会调用。

三、ChannelInbounderHandler
ChannelInboundHandler 的生命周期方法如下,当接收到数据或者与之关联的 Channel 状态改变时调用。

可以看到,这些方法与 Channel 的生命周期接近。
其中 channelRead 和 channelReadComplete 方法在读操作开始和完成时调用。
另外,channelWritabilityChanged 方法在 channel 写状态发生变化时调用。
四、ChannelOutboundHandler
ChannelOutboundHandler 提供了出站操作时调用的方法。
另外,它具有在请求时演示操作或者事件的能力。比如,当你在写数据到远程的过程中被意外暂停,你可以延时进行刷新操作,然后在迟些时候继续。
下面是提供的方法(继承自 ChannelHandler 未列出来):

五、资源管理
Netty 使用引用计数器来处理池化的 ByteBuf。所以当 ByteBuf 完全处理后,要确保引用计数器被调整。
当你覆盖了 channelRead 操作,在处理完消息之后,需要释放它,如下:
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
/**
* 收到数据时调用
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 丢弃收到的数据
((ByteBuf) msg).release();
}
}
Netty 提供了一个特殊的称为 SimpleChannelInboundHander 的实现,该实现将在用户通过 channelRead0() 方法处理完数据之后,自动释放该消息。
当你在处理写操作,并丢弃消息时,你需要通知 ChannelPromise 数据已经被处理,如下:
public class DiscardOutbounderHandler extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx,
Object msg, ChannelPromise promise) throws Exception {
ReferenceCountUtil.release(msg); // 释放资源
promise.setSuccess(); // 通知 ChannelPromise 数据已经被处理
}
}
六、使用 ChannelHandler
下图展示了 ChannelPipeline,Channel,ChannelHandler 和 ChanelHandlerContext 的关系:

- Channel 绑定到 ChannelPipeline
- ChannelPipeline 绑定到包含 ChannelHandler 的 Channel
- ChannelHandler
- 当添加 ChannelHandler 到 ChannelPipeline 时,ChannelHandlerContext 被创建
如果要完成一个写操作,有以下两种方式:
第一种就是从 ChannelHandlerContext 获取到 Channel 的引用,执行 Channel 上的 write() 方法,如下:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 丢弃收到的数据
((ByteBuf) msg).release();
Channel channel = ctx.channel(); // 获取channel引用
// 通过channel写缓存
channel.write(Unpooled.copiedBuffer("Netty", CharsetUtil.UTF_8));
}
第二种是从 ChannelHandlerContext 获取到 ChannelPipeline 的引用,执行 ChannelPipeline 上的 write() 方法,如下:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ChannelPipeline pipeline = ctx.pipeline(); // 获取pipeline引用
// 通过pipeline写缓存
pipeline.write(Unpooled.copiedBuffer("Netty", CharsetUtil.UTF_8));
}
写操作流程如下:

- 事件传递给 ChannelPipeline 的第一个 ChannelHandler
- ChannelHandler 通过关联的 ChannelHandlerContext 传递事件给 ChannelPipeline 中的下一个 ChannelHandler
- 与 2 类似
但是有些时候不希望总是从 ChannelPipeline 的第一个 ChannelHandler 开始事件,我们希望从一个特定的 ChannelHandler 开始处理。你必须引用于此 ChannelHandler 的前一个 ChannelHandler 关联的 ChannelHandlerContext,利用它调用与自身关联的 ChannelHandler 的下一个 ChannelHandler。如下:
ChannelHandlerContext ctx = context; // 获得 ChannelHandlerContext引用
// write()将会把缓冲区发送到下一个ChannelHandler
ctx.write(Unpooled.copiedBuffer("Netty in Action", CharsetUtil.UTF_8));
流程如下:

- 直接从特定的 ChannelHandler 开始执行
- 事件发送到下一个 ChannelHandler
- 经过最后一个 ChannelHandler 后,事件从 ChannelPipeline 移除
Netty入门(五)ChanneHandler的更多相关文章
- Netty入门
一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...
- Netty入门教程——认识Netty
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...
- Netty入门与实战教程总结分享
前言:都说Netty是Java程序员必须要掌握的一项技能,带着不止要知其然还要知其所以然的目的,在慕课上找了一个学习Netty源码的教程,看了几章后着实有点懵逼.虽然用过Netty,并且在自己的个人网 ...
- openresty 前端开发入门五之Mysql篇
openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...
- Netty(五)序列化protobuf在netty中的使用
protobuf是google序列化的工具,主要是把数据序列化成二进制的数据来传输用的.它主要优点如下: 1.性能好,效率高: 2.跨语言(java自带的序列化,不能跨语言) protobuf参考文档 ...
- Thinkphp入门 五 —模型 (49)
原文:Thinkphp入门 五 -模型 (49) [数据库操作model模型] model 模型 数据库操作 tp框架主要设计模式:MVC C:controller 控制器 shop/Li ...
- DevExpress XtraReports 入门五 创建交叉表报表
原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...
- Netty入门之客户端与服务端通信(二)
Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...
- Netty入门之HelloWorld
Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...
- 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?
本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言 老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...
随机推荐
- WPF ContextMenu的使用
<Grid.ContextMenu > <ContextMenu> <MenuItem Header="增加" Click="MenuIte ...
- [MongoDB] mongodb与php
windows上安装mongodb的php扩展 下载地址https://s3.amazonaws.com/drivers.mongodb.org/php/index.html 找到对应的php版本的d ...
- 【ibatis】IBatis介绍
Ⅰ .什么是Ibatis? ① iBATIS的是一个持久层框架,它能够自动在 Java, .NET, 和Ruby on Rails中与SQL数据库和对象之间的映射.映射是从应用程序逻辑封装在XML配置 ...
- 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)
学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...
- 【代码笔记】iOS-4个可以单独点击的button
一,效果图. 二,工程图. 三,代码. ViewController.m #import "ViewController.h" @interface ViewController ...
- Hibernate 中配置属性详解(hibernate.properties)
Hibernate能在各种不同环境下工作而设计的, 因此存在着大量的配置参数.多数配置参数都 有比较直观的默认值, 并有随 Hibernate一同分发的配置样例hibernate.properties ...
- 关于ArrayAdapter的getCount()的方法会造成空指针异常的分析
在继承了ArrayAdapter重新getCount()的方法后,比如 public int getCount() { return 3; } 若在活动中调用setAdapter()的方法前,List ...
- Android Studio 编译: Program type already present: XXX 解决方案
3情况1:个例 build.gradle 中 dependencies { classpath 'com.android.tools.build:gradle:3.1.1' // } 改成 depen ...
- linux svn配置与使用
svn错误码对照表: http://docs.sharpsvn.net/current/html/T_SharpSvn_SvnErrorCode.htm https://www.cnblogs ...
- [Android] Spinners介绍及用法
本文地址:http://www.cnblogs.com/rossoneri/p/4366018.html Spinners介绍 Spinners提供了从一个集(set)中选择某个值(value)的一个 ...