前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Netty|03 Handler运行顺序

Netty|03 Handler运行顺序

作者头像
微笑的小小刀
发布2019-09-10 15:11:33
1.5K0
发布2019-09-10 15:11:33
举报
文章被收录于专栏:java技术大本营

测试handler的运行过程

1、测试用例包括两个InboundHandler与OuuboundHandler 2、所有的导包都没有在代码中,需要自行添加

1、Demo搭建

2、编写NettyServer

代码语言:javascript
复制
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
//        创建线程池 接受连接
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
//        创建线程池,处理io
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
//        创建服务器端启动助手
        ServerBootstrap serverBootstrap = new ServerBootstrap();
//        配置启动助手
        serverBootstrap.group(bossGroup, workGroup)//设置两个线程池
                .channel(NioServerSocketChannel.class)//使用作为服务器端的通道实现
                .option(ChannelOption.SO_BACKLOG, 128)//设置线程队列中等待连接的个数
                .childOption(ChannelOption.SO_KEEPALIVE, true)//保持活动连接状态
                .childHandler(new ChannelInitializer<SocketChannel>() { //创建通道初始化的对象
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast("decoder",new StringDecoder());
                        pipeline.addLast("encoder",new StringEncoder());
                        pipeline.addLast(new NettyServerOutHandler());
                        pipeline.addLast(new NettyServerOutHandler2());
                        pipeline.addLast(new NettyServerInHandler());
                        pipeline.addLast(new NettyServerInHandler2());
                    }
                });
        System.out.println("----------------server is ready--------------------");
        ChannelFuture cf = serverBootstrap.bind(9999).sync();//绑定端口,异步
        System.out.println("----------------server is starting--------------------");
//        关闭通道、关闭通道组
        cf.channel().closeFuture().sync();
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();

    }
}

3、编写NettyServerInHandler和NettyServerInHandler2

代码语言:javascript
复制
public class NettyServerInHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelRegistered");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelUnregistered");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelActive");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelInactive");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelReadComplete");
        ctx.channel().writeAndFlush("服务器发送0-0");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("NettyServerInHandler userEventTriggered");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler channelWritabilityChanged");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("NettyServerInHandler exceptionCaught");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("NettyServerInHandler channelRead接收到客户端的数据:"+(String)msg);
//        事件传播
        ctx.fireChannelRead(msg);
    }
}
代码语言:javascript
复制
public class NettyServerInHandler2 extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelRegistered");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelUnregistered");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelActive");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelInactive");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelReadComplete");
        ctx.channel().writeAndFlush("服务器发送0-0");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("NettyServerInHandler2 userEventTriggered");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        System.out.println("NettyServerInHandler2 channelWritabilityChanged");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("NettyServerInHandler2 exceptionCaught");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("NettyServerInHandler2 channelRead接收到客户端的数据:"+(String)msg);
    }
}

4、编写NettyServerOutHandler与NettyServerOutHandler2

代码语言:javascript
复制
public class NettyServerOutHandler extends ChannelOutboundHandlerAdapter {
    /**
     * 写数据
     * @param ctx
     * @param msg
     * @param promise
     * @throws Exception
     */
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        System.out.println("ServerOutHandler:"+(String) msg);
        ctx.write(msg,promise);
    }
}
代码语言:javascript
复制
public class NettyServerOutHandler2 extends ChannelOutboundHandlerAdapter {
    /**
     * 写数据
     * @param ctx
     * @param msg
     * @param promise
     * @throws Exception
     */
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        System.out.println("ServerOutHandler2:"+(String) msg);
        ctx.write(msg,promise);
    }
}

5、编写NettyClient

代码语言:javascript
复制
public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
//        创建一个线程组
        NioEventLoopGroup group = new NioEventLoopGroup();
        //2. 创建客户端的启动助手,完成相关配置
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)//3. 设置线程组
                .channel(NioSocketChannel.class)//4. 设置客户端通道的实现类
                .handler(new ChannelInitializer<SocketChannel>() {//5. 创建一个通道初始化对象
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast("encoder",new StringEncoder());
                        pipeline.addLast("decoder",new StringDecoder());
                        pipeline.addLast(new NettyClientHandler());//6.往Pipeline链中添加自定义的handler
                    }
                });
        System.out.println("......Client is  ready......");

        //7.启动客户端去连接服务器端  connect方法是异步的   sync方法是同步阻塞的
        ChannelFuture cf = bootstrap.connect("127.0.0.1", 9999).sync();
//        发送消息
        cf.channel().writeAndFlush("哈哈哈");
//        关闭连接
        cf.channel().closeFuture().sync();

    }
}

6、编写NettyClientHandler

代码语言:javascript
复制
public class NettyClientHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 读数据
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("服务器发来消息:"+msg);
    }
}

7、运行结果

服务器端: ----------------server is ready-------------------- ----------------server is starting-------------------- NettyServerInHandler channelRegistered NettyServerInHandler channelActive NettyServerInHandler channelRead接收到客户端的数据:哈哈哈 NettyServerInHandler2 channelRead接收到客户端的数据:哈哈哈 NettyServerInHandler channelReadComplete ServerOutHandler2:服务器发送0-0 ServerOutHandler:服务器发送0-0

客户端: ......Client is ready...... 服务器发来消息:服务器发送0-0

强制关闭客户端: NettyServerInHandler channelReadComplete ServerOutHandler2:服务器发送0-0 ServerOutHandler:服务器发送0-0 NettyServerInHandler exceptionCaught NettyServerInHandler userEventTriggered NettyServerInHandler channelInactive NettyServerInHandler channelUnregistered

8、分析结果

由此可以看出,inboundHandler的执行顺序是: channelRegistered→channelActive→channelRead→传播到第二个inboundhandler的channelRead →channelReadComplete→往上一个ServerOutHandler2→再往上ServerOutHandler传播,最后发送到客户端NettyClientInHandler的channelRead中接收到数据。

异常出现的执行顺序: channelReadComplete→exceptionCaught→userEventTriggered→channelInactive→channelUnregistered。

分析得出: 1、通道先注册再会处于活跃状态 2、通道read结束后才会触发readComplete 3、当inboundHandler中触发一个write方法,就会往该链上的上一个outboundHandler中触发write方法,然后再往上触发,直到没有outboundHandler为止,就会发送消息到客户端。 4、通道关闭会再次触发readComplete,然后触发异常方法exceptionCaught,接下来触发userEventTriggered,最后触发channelInactive与channelUnregistered。 5、readComplete方法是在所有的inboundHandler跑完之后才触发的方法,并且只会触发第一个inboundHandler的readComplete方法。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java技术大本营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Demo搭建
  • 2、编写NettyServer
  • 3、编写NettyServerInHandler和NettyServerInHandler2
  • 4、编写NettyServerOutHandler与NettyServerOutHandler2
  • 5、编写NettyClient
  • 6、编写NettyClientHandler
  • 7、运行结果
  • 8、分析结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档