Netty channelHandler注意事項——super.channelRead(ctx, msg)
创始人
2024-05-31 10:29:26

通过nioSocketChannel.pipeline()的addLast添加入站处理器,如果有多个必须显示的唤醒下一个入站处理器,否则执行链中间会断掉。

protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {log.debug(nioSocketChannel.toString());//添加各种处理器nioSocketChannel.pipeline().addLast(new LoggingHandler());nioSocketChannel.pipeline().addLast(new StringDecoder());//字符串解析器nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {log.debug("msg 1 : {}",msg);//这里未调用唤醒下一个处理器}});nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {log.debug("msg 1 : {}",msg);super.channelRead(ctx, msg);}});
}

执行结果:

 解决方法:

super.channelRead(ctx, msg);源码:

该函数调用的是:

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ctx.fireChannelRead(msg);
}

进一步跟踪调用:

public ChannelHandlerContext fireChannelRead(final Object msg) {//找到下一个handler并执行invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);return this;
}
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);EventExecutor executor = next.executor();if (executor.inEventLoop()) {next.invokeChannelRead(m);} else {//新启动一个线程,执行新的处理器executor.execute(new Runnable() {@Overridepublic void run() {next.invokeChannelRead(m);}});}
}

附加:入站处理器调用出站后,分别有:

ChannelHandlerContext.writeAndFlush:从当前处理器往前找
nioSocketChannel.writeAndFlush:从最后一个处理依次往前找。

上图执行顺序:

入站1-》入站2-》入站2调用出站-》当前往前找-》出站1

NioSocketChannel 会从后往前找出站处理器,
ChannelHandlerContext:会从当前处理器往前找出战处理器。

 

                        nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("msg 1 : " + msg);//唤醒下一个handler,同时可以将消息进一步处理super.channelRead(ctx, msg + "我已经被处理过");}});nioSocketChannel.pipeline().addLast(new ChannelOutboundHandlerAdapter() {@Overridepublic void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {System.out.println("调用出战处理器 1");System.out.println(msg.toString());super.write(ctx, msg, promise);}});nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {//得到消息,是第一个handler处理过后的内容System.out.println("msg 2 : " + msg);//ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("出出出出出".getBytes()));//nioSocketChannel 会从最后一个依次向前找出站处理器nioSocketChannel.writeAndFlush(ctx.alloc().buffer().writeBytes("出出出出出".getBytes()));}});nioSocketChannel.pipeline().addLast(new ChannelOutboundHandlerAdapter() {@Overridepublic void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {System.out.println("调用出战处理器 2");System.out.println(msg.toString());super.write(ctx, msg, promise);}});nioSocketChannel.pipeline().addLast(new ChannelOutboundHandlerAdapter() {@Overridepublic void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {System.out.println("调用出战处理器 3");System.out.println(msg.toString());super.write(ctx, msg, promise);}});}
nioSocketChannel   依次从最后往前调用出站处理器,执行顺序为:  3   2  1

 

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...