为什么在使用MessageToByteEncoder时需要调用ctx.writeAndFlush

时间:2013-10-13 20:18:19

标签: netty

我在Netty上实现SIP服务器,使用Netty 3.x一切正常。但是我决定升级到Netty 4,因为定义良好的线程模型但事情发生了很大的变化,我迷失了。我最初的问题(我的大部分工作,但对我来说还没有意义)是关于MessageToByteEncoder以及为什么我必须自己打电话给ctx.writeAndFlush

引导程序:

private void createTCPListeningPoint() {
    this.serverBootstrap = new ServerBootstrap();

    this.serverBootstrap.group(this.bossGroup, this.workerGroup)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(final SocketChannel ch) throws Exception {
                    final ChannelPipeline pipeline = ch.pipeline();
                    pipeline.addLast("decoder", new SipFrameDecoder(Protocol.TCP));
                    pipeline.addLast("encoder", new SipMessageEncoder());
                    pipeline.addLast("handler", NettyNetworkStack.this.sipHandler);
                }
            });
    // .option(ChannelOption.SO_BACKLOG, 128)
    // .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
    // .childOption(ChannelOption.SO_KEEPALIVE, true)
    // .childOption(ChannelOption.TCP_NODELAY, true);
}

(绑定操作稍后进行,此处未显示)

由于传入的管道正在工作(解码器和处理程序正在被调用),唯一有趣的部分是SipMessageEncoder,它非常简单,下面是代码。另请注意,我一直在玩各种选项,但怀疑,我没有发现任何改变这种行为的组合。

编码器:

public final class SipMessageEncoder extends MessageToByteEncoder<SipMessage> {

@Override
protected void encode(final ChannelHandlerContext ctx, final SipMessage msg, final ByteBuf out) throws Exception {
    final Buffer b = msg.toBuffer();
    for (int i = 0; i < b.getReadableBytes(); ++i) {
        out.writeByte(b.getByte(i));
    }
    out.writeByte(SipParser.CR);
    out.writeByte(SipParser.LF);
    // ctx.writeAndFlush(out);
}

}

SipMessageSipParser等来自我的其他开源项目pkts.io但与此问题无关。只要知道SipMessage.toBuffer()基本上只是吐出一个原始的byte[],然后我将转移到Netty传入的ByteBuff

除非我执行ctx.writeAndFlush(out),否则上述代码无效。但是,我认为,就像在Netty 3中一样,这个略高级编码器的目的是保护我免受这些细节的影响。通过代码逐步调试ByteBuf写入ctx但不刷新,我想这是它没有出现在套接字上的原因。所以,我的问题很简单:

  • 为什么我在使用ctx.writeAndFlush时必须自己致电SipMessageEncoder。 Factorial示例中的NumberEncoder不执行此操作并查看HTTP编解码器,我无法看到它确实如此,显然我错过了一些明显的东西。
  • 此外,ByteBuf正被写入上下文但从未被刷新,所以什么时候会?我试图通过单个TCP连接(使用sipp)推动大量流量,看看是否最终会强制刷新但不会出现任何问题。

顺便说一句,我也尝试使用MessageToMessageEncoder并在上下文中分配ByteBuf并将其添加到List但结果相同。

Btw2 - 我正在使用Netty 4.0.10.Final

谢谢,

/纳斯

1 个答案:

答案 0 :(得分:1)

在向频道发送消息时,您是否在其他地方调用了flush()?

  

“..你必须非常小心,不要忘记在写完东西之后再调用ctx.flush()。或者,你可以使用快捷方法writeAndFlush()”

实际上,您不需要在SipMessageEncoder中调用write(),因为消息将由父MessageToByteEncode写入。如果以前没有完成,你只需要调用flush()。