2013-10-13 30 views
1

我在Netty之上實現爲SIP服務器,並且所有內容都使用Netty 3.x正常工作。不過,我決定升級到Netty 4,因爲它有明確的線程模型,但事情發生了很大的變化,我迷了路。我最初的問題(我得到的大部分工作,但它對我來說不太合理)是關於MessageToByteEncoder和爲什麼我必須自己打電話ctx.writeAndFlush爲什麼在使用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

你調用flush()其他地方寫一個消息渠道是什麼時候?

「..你必須非常小心,在寫完東西之後不要忘記調用ctx.flush()。另外,您也可以使用快捷方法writeAndFlush()」

其實你並不需要調用的SipMessageEncoder寫(),因爲該消息將被父MessageToByteEncode寫的。你只需要調用flush( )如果以前沒有做過。

+1

喜伊戈爾, 不,我不叫齊平,並沒有實際的幫助,因爲我不寫任何東西我自己。也許我誤解了MessageToByteEncoder的使用,但我的印象是,我將一個對象轉換爲另一個對象(在這種情況下是ByteBuf),並在稍後的一段時間內將其寫入並刷新,我相信我只是錯過了一些非常明顯的東西,如果我做了ctx。它在bytebuf上的writeAndFlush工作,但是我不明白MessageToByteEncoder的重點。 – jonbo372

+0

嗨,伊戈爾,其實我想我明白你的意思。不,我不會在我的SipMessageEncoder中調用flush,也許問題出在哪裏。我會給出一個去,如果這樣的作品,然後感謝讓我在正確的軌道上!非常感謝。我會盡快更新,但我首先嚐試實際工作:-) – jonbo372

+1

您會發現,寫入通道的所有消息都駐留在輸出緩衝區中,直到您調用flush()爲止。主要使用場景如下:將消息寫入頻道,然後使用flush()。每條消息都由MessageToByteEncoder序列化。這裏不需要調用write()。在最後flush()之後,所有消息將被寫入該行。如果你在SipMessageEncoder中沒有調用flush()方法。 –

相關問題