先看一个例子.

有一个简单 Server

public class SimpleServer {

    public static void main(String[] args) throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_REUSEADDR, true)
.childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new SimpleDuplex1());
ch.pipeline().addLast(new SimpleDuplex2());
ch.pipeline().addLast(new SimpleServerHandler());
}
});
b.bind(8090).sync().channel().closeFuture().sync();
}
}

Handler 详情如下

public class SimpleDuplex1 extends ChannelDuplexHandler {

    @Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("---- write 1 ----");
super.write(ctx, msg, promise);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("---- read 1 ----");
super.channelRead(ctx, msg);
}
} public class SimpleDuplex2 extends ChannelDuplexHandler { @Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("---- write 2 ----");
super.write(ctx, msg, promise);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("---- read 2 ----");
super.channelRead(ctx, msg);
}
}
public class SimpleServerHandler extends ChannelDuplexHandler {

    @Override
public void channelRead(ChannelHandlerContext ctx, final Object msg) throws Exception {
ctx.channel().writeAndFlush(ByteBufAllocator.DEFAULT.buffer().writeBytes("OK".getBytes())).addListener(ChannelFutureListener.CLOSE);
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("----- INACTIVE -----");
super.channelInactive(ctx);
} @Override
public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
System.out.println("----- CLOSE -----");
super.close(ctx, future);
}
}

启动 Server 以后, 使用 telnet 发送数据查看执行结果

---- read 1 ----
---- read 2 ----
成功
---- write 2 ----
---- write 1 ----
----- CLOSE -----
----- INACTIVE -----

1. 先来看看执行顺序, 可见, inbound 的顺序是跟 add 顺序一致的, 而 outbound 的顺序是跟 add 顺序相反的

以及, read 的 IO 触发顺序是 "socketChannel.read() -> 顺序 handler -> TailContext.channelRead().releaseMsg"

而 write 的 IO 触发顺序是 "逆序 handler -> HeadContext.socketChannel.write()"

也就是说 read 是先触发 socket 的 read IO 时间, 再进入 handler, 而如果我们最后一个 handler 未能完全处理消息, 调用了 super.channelRead, 则会进入 TailContext. 此时TailContext 会打出 debug 消息告诉你消息进入了最后一个 Handler 而未被处理. 因为一般来讲都应该在自己的 handler 里把消息处理掉. 而不是让他进入到默认 handler 里.

而对于 write 来说, 则是先进入自定义 handler, 最后在进入 HeadContext 触发 IO 时间

2. 再来说说 close 与 channelInactive

前面说到了. Outbound 的顺序是最后才执行到 HeadContext 来执行实际的 IO 操作, close 也是一样, 当你调用 channle.close 的时候, 先会经过你的 handler . 最后调用 HeadContext.socketChannel.close(). 所以, 在我们的 Handler 中, 先会打印 "---- CLOSE ----" 然后再调用实际的 socketChannel.close. 最后, 当 close 成功时, 触发 ChannelInactive 时间.

所以说 close 与 channelInactive 的关系是 close 是主动关闭 channel 的动作, 而 channelInactive 是关闭成功后收到通知的事件.

Netty 的 inbound 与 outbound, 以及 InboundHandler 的 channelInactive 与 OutboundHandler 的 close的更多相关文章

  1. pcie inbound、outbound及EP、RC间的互相訪问

    Inbound:PCI域訪问存储器域 Outbound:存储器域訪问PCI域 RC訪问EP: RC存储器域->outbound->RC PCI域->EP PCI域->inbou ...

  2. netty中的Channel、ChannelPipeline

    一.Channel与ChannelPipeline关系 每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline.这项关联是永久性 的:Channel 既不能附加另外一个 ...

  3. netty中的引导Bootstrap客户端

    一.Bootstrap Bootstrap 是 Netty 提供的一个便利的工厂类, 我们可以通过它来完成 Netty 的客户端或服务器端的 Netty 初始化.下面我以 Netty 源码例子中的 E ...

  4. Netty版本升级血泪史之线程篇

    1. 背景 1.1. Netty 3.X系列版本现状 根据对Netty社区部分用户的调查,结合Netty在其它开源项目中的使用情况,我们可以看出目前Netty商用的主流版本集中在3.X和4.X上,其中 ...

  5. netty源码学习

    概述 Netty is an asynchronous event-driven network application framework for rapid development of main ...

  6. Pipeline inbound(netty源码7)

    netty源码死磕7  Pipeline 入站流程详解 1. Pipeline的入站流程 在讲解入站处理流程前,先脑补和铺垫一下两个知识点: (1)如何向Pipeline添加一个Handler节点 ( ...

  7. 【Netty】(8)---理解ChannelPipeline

    ChannelPipeline ChannelPipeline不是单独存在,它肯定会和Channel.ChannelHandler.ChannelHandlerContext关联在一起,所以有关概念这 ...

  8. Netty 核心组件 Pipeline 源码分析(一)之剖析 pipeline 三巨头

    目录大纲: 前言 ChannelPipeline | ChannelHandler | ChannelHandlerContext 三巨头介绍 三巨头编织过程(创建过程) ChannelPipelin ...

  9. Netty源码分析第4章(pipeline)---->第1节: pipeline的创建

    Netty源码分析第四章: pipeline 概述: pipeline, 顾名思义, 就是管道的意思, 在netty中, 事件在pipeline中传输, 用户可以中断事件, 添加自己的事件处理逻辑, ...

随机推荐

  1. icePDF去水印方法

    原文:http://www.cnblogs.com/pcheng/p/5711660.html 1.首先下载到icepdf的架包. 2.用解压缩软件,对该jar文件进行解压,得到名为icepdf-co ...

  2. Thoughtful function is also good for investigation

    Did you know how many friends in your IM? Some of them you are not familiar with, but your friends c ...

  3. Struts2 XML配置详解

    struts官网下载地址:http://struts.apache.org/   1.    深入Struts2的配置文件 本部分主要介绍struts.xml的常用配置. 1.1.    包配置: S ...

  4. 初学python之urllib

    urllib.request urlopen()urllib.urlopen(url, data, proxies) :创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远 ...

  5. Tesla P4 在深度学习上的性价比辗压目前所有量产的FPGA

    7000的价格, 5.5T FP, 75W不到的功耗,性能接近M40,敢问目前有哪个量产的FPGA能做到?还不算开发和维护的难度...KU115光PCIE+DMA+DDR4 controller+AX ...

  6. 浅析NRF51822合并文件之app_valid_setting_apply

    [原创出品§转载请注明出处] 出处:http://www.cnblogs.com/libra13179/p/5787084.html 我们打开app_valid_setting_apply.hex如下 ...

  7. Data Transformation / Learning with Counts

    机器学习中离散特征的处理方法 Updated: August 25, 2016 Learning with counts is an efficient way to create a compact ...

  8. 如何优雅的实现INotifyPropertyChanged接口

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ...

  9. web聊天室

    开发一个web聊天室 功能需求: 1.用户可以与好友一对一聊天 2.群聊 所需知识 1.Django 2.bootstrap 3.CSS 4.ajax 涉及到的新的知识点 1.如果设计表结构的时候,一 ...

  10. macbook 重装win7

    若是第一次已经成功好了,并且把第一次的安装U盘WININSTALL内容保存完好的前提下, win7要重新安装. 先进入Boot Camp移除Windows,备份好你的WIN系统的重要文件. 把第一次的 ...