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

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();
    }
}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);
    }
}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);
    }
}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);
    }
}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);
    }
}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();
    }
}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);
    }
}服务器端: ----------------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
由此可以看出,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方法。