Netty 出站处理程序没有被调用

Ram*_* KS 3 netty

我正在使用 Netty 4.1.0.Final 并且我面临消息未通过出站处理程序传递的问题。我发布了一个示例程序,其中有一个入站处理程序和一个出站处理程序。入站处理程序在 ChannelHandlerContext 中使用 writeAndFlush,我的理解是它应该将消息转发到管道中第一个可用的出站处理程序。为简单起见,忽略内存管理。

引导代码

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .localAddress(12021)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new TestHandler1(), new TestOutHandler1());
                 }
             });
ChannelFuture future = bootstrap.bind().sync();
System.out.println("Server Started...");
    future.channel().closeFuture().sync();
    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();
    System.out.println("Server Shutdown");
Run Code Online (Sandbox Code Playgroud)

入站处理程序代码

public class TestHandler1 extends ChannelInboundHandlerAdapter {


private static Log logger = LogFactory.getLog(TestHandler1.class);

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    logger.info("channelRead");
    ctx.writeAndFlush(msg);
}
Run Code Online (Sandbox Code Playgroud)

}

出站处理程序代码

public class TestOutHandler1 extends ChannelOutboundHandlerAdapter {

private static Log logger = LogFactory.getLog(TestOutHandler1.class);

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    logger.info("write");
    ctx.writeAndFlush(msg);
}
Run Code Online (Sandbox Code Playgroud)

}

输出

信息 TestHandler1:通道读取

如果我通过在通道而不是 ChannelHandlerContext 上执行 writeAndFlush() 来如下更改我的入站处理程序,我将获得预期的输出

修改的入站处理程序

public class TestHandler1 extends ChannelInboundHandlerAdapter {

private static Log logger = LogFactory.getLog(TestHandler1.class);

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    logger.info("channelRead");
    ctx.channel().writeAndFlush(msg);
}
Run Code Online (Sandbox Code Playgroud)

}

输出

信息 TestHandler1:通道读取

信息 TestOutHandler1:write

根据诺曼在以下链接中的解释,我理解 ChannelHandlerContext.write(...) 应该通过它前面的 ChannelOutboundHandlers,在我的情况下,它是唯一的出站处理程序。

诺曼的解释

让我知道我的理解是错误的还是我遗漏了什么。

Nor*_*rer 5

这是因为您在ChannelOutboundHandler之前ChannelInboundHandler添加将会从添加 的点ChannelPipeline. ChannelHandlerContext.writeAndFlush(...)开始。因此在它会按预期工作之前添加。ChannelPipelineChannelHandlerChannelOutboundHandler


小智 5

以前的答案很棒,我想解释问题的另一个方面:通过调用ctx.writeAndFlush()ctx.channel.writeAndFlush()

频道结构

  1. ctx.writeAndFlush()
    在当前 ctx 之前找到第一个 OutboundHandler。在您的频道中,未找到任何内容。所以只打印一个信息。
  2. ctx.channel.writeAndFlush()
    实际上,ctx.channel.writeAndFlush()会调用 pipeline.tail.writeAndFlush()。这相当于writeAndFlush()在您的频道中调用tail ctx。这样,TestOutHandler1 就会被找到并被TestOutHandler1.write()调用。然后打印两个信息。