netty使用(6)handler 执行顺序问题
Netty中,可以注册多个handler。ChannelInboundHandler按照注册的先后顺序执行;ChannelOutboundHandler按照注册的先后顺序逆序执行,
1、ChannelInboundHandler之间的传递,通过调用 ctx.fireChannelRead(msg) 实现;调用ctx.write(msg) 将传递到ChannelOutboundHandler。
2、ctx.write()方法执行后,需要调用flush()方法才能令它立即执行。
3、ChannelOutboundHandler 在注册的时候需要放在最后一个ChannelInboundHandler之前,否则将无法传递到ChannelOutboundHandler。
import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class HelloServer { public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 注册两个OutboundHandler,执行顺序为注册顺序的逆序,所以应该是OutboundHandler2 OutboundHandler1 ch.pipeline().addLast(new OutboundHandler1()); ch.pipeline().addLast(new OutboundHandler2()); // 注册两个InboundHandler,执行顺序为注册顺序,所以应该是InboundHandler1 InboundHandler2 ch.pipeline().addLast(new InboundHandler1()); ch.pipeline().addLast(new InboundHandler2()); } }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { HelloServer server = new HelloServer(); server.start(8000); } } class InboundHandler1 extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("inboundHandler 1 read"); // 通知执行下一个InboundHandler ctx.fireChannelRead(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("inboundHandler 1 read complete"); ctx.flush(); } } class InboundHandler2 extends ChannelInboundHandlerAdapter { @Override // 读取Client发送的信息,并打印出来 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("inboundHandler 2 read"); ByteBuf result = (ByteBuf) msg; byte[] result1 = new byte[result.readableBytes()]; result.readBytes(result1); String resultStr = new String(result1); System.out.println("Client said:" + resultStr); result.release(); ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //logger.info("InboundHandler2.channelReadComplete"); System.out.println("inboundHandler 2 read complete"); ctx.flush(); } } class OutboundHandler1 extends ChannelOutboundHandlerAdapter { @Override // 向client发送消息 public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { // logger.info("OutboundHandler1.write"); System.out.println("outboundHandler 1 write"); String response = "I am ok!"; ByteBuf encoded = ctx.alloc().buffer(4 * response.length()); encoded.writeBytes(response.getBytes()); ctx.write(encoded); ctx.flush(); } } class OutboundHandler2 extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { //logger.info("OutboundHandler2.write"); // 执行下一个OutboundHandler System.out.println("outboundHandler 2 write"); super.write(ctx, msg, promise); } }
输出为
inboundHandler 1 read inboundHandler 2 read Client said:are you alright? outboundHandler 2 write outboundHandler 1 write inboundHandler 1 read complete