本节主要讨论了 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 的关系:

  

  1. Channel 绑定到 ChannelPipeline
  2. ChannelPipeline 绑定到包含 ChannelHandler 的 Channel
  3. ChannelHandler
  4. 当添加 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));
}

  写操作流程如下:

  

  1. 事件传递给 ChannelPipeline 的第一个 ChannelHandler
  2. ChannelHandler 通过关联的 ChannelHandlerContext 传递事件给 ChannelPipeline 中的下一个 ChannelHandler
  3. 与 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));

  流程如下:

  

  1. 直接从特定的 ChannelHandler 开始执行
  2. 事件发送到下一个 ChannelHandler
  3. 经过最后一个 ChannelHandler 后,事件从 ChannelPipeline 移除

Netty入门(五)ChanneHandler的更多相关文章

  1. Netty入门

    一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...

  2. Netty入门教程——认识Netty

    什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...

  3. Netty入门与实战教程总结分享

    前言:都说Netty是Java程序员必须要掌握的一项技能,带着不止要知其然还要知其所以然的目的,在慕课上找了一个学习Netty源码的教程,看了几章后着实有点懵逼.虽然用过Netty,并且在自己的个人网 ...

  4. openresty 前端开发入门五之Mysql篇

    openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...

  5. Netty(五)序列化protobuf在netty中的使用

    protobuf是google序列化的工具,主要是把数据序列化成二进制的数据来传输用的.它主要优点如下: 1.性能好,效率高: 2.跨语言(java自带的序列化,不能跨语言) protobuf参考文档 ...

  6. Thinkphp入门 五 —模型 (49)

    原文:Thinkphp入门 五 -模型 (49) [数据库操作model模型] model  模型  数据库操作 tp框架主要设计模式:MVC C:controller   控制器   shop/Li ...

  7. DevExpress XtraReports 入门五 创建交叉表报表

    原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...

  8. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

  9. Netty入门之HelloWorld

    Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...

  10. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

随机推荐

  1. Git使用(一)——Cygwin

    1.下载2.安装镜像:1)上海交大的FTP:ftp://ftp.sjtu.edu.cn/sites/cygwin.com/pub/cygwin/2)163的镜像:http://mirrors.163. ...

  2. sqlhelper中事务的简单用法

    sql1="INSERT INTO tablename(Id,col1,col2) VALUES(@Id,@col1,@col2) update tablename2 set col=@co ...

  3. Tomcat7.0安装配置详细(图文)

    说明:Tomcat服务器上一个符合J2EE标准的Web服务器,在tomcat中无法运行EJB程序,如果要运行可以选择能够运行EJB程序的容器WebLogic,WebSphere,Jboss等Tomca ...

  4. java设计模式-----20、模板方法模式

    概念: Template Method模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为. 模板方法模式的应 ...

  5. HDU6188

    Duizi and Shunzi Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. Code Signal_练习题_arrayMaxConsecutiveSum

    Given array of integers, find the maximal possible sum of some of its k consecutive elements. Exampl ...

  7. form表单提交注意事项

    1.在一个form表单中,若只有一个input(不管type是什么),按回车键表单会自动提交,但是当表单中存在多个input时,按回车键不会执行任何操作,这是form表单的一个特性. 2.在一个表单中 ...

  8. ArcGIS基于DEM计算水流方向的方法(D8算法)

    ArcGIS采用D8算法计算水流方向(9.3.1后新增),输入数据应首先完成了洼地填充处理: One of the keys to deriving hydrologic characteristic ...

  9. 安装google,多试试

    对于谷歌Chrome32位版本,使用如下链接: wget https://dl.google.com/linux/direct/google-chrome-stable_current_i386.de ...

  10. RecyclerView源码解析 - 分割线

    猜想:   既然考虑了分割线,那么子View在测量时候肯定要去考虑分割线留出的位置    直接measureChild()方法 猜想: 分割线会调用绘制的方法 onDraw()