Netty 的 inbound 与 outbound, 以及 InboundHandler 的 channelInactive 与 OutboundHandle_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2920 | 回复: 0   主题: Netty 的 inbound 与 outbound, 以及 InboundHandler 的 channelInactive 与 OutboundHandle        下一篇 
wulcan
版主
等级:中校
经验:1795
发帖:124
精华:0
注册:2014-3-19
状态:离线
发送短消息息给wulcan 加好友    发送短消息息给wulcan 发消息
发表于: IP:您无权察看 2015-12-10 15:31:10 | [全部帖] [楼主帖] 楼主

先看一个例子.

有一个简单 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 是关闭成功后收到通知的事件.







                                                                                                                      --转自



赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论