2013-03-22 46 views
0

我正在使用Netty,並且似乎不會調用ChannelPipeline中的FrameDecoder,除非/直到收到回車。例如,我有我寫嘗試檢測,當一個完整的JSON字符串已經收到了以下解碼器:Netty FrameDecoder在ChannelPipeline中沒有回車沒有被調用?

public class JsonDecoder extends FrameDecoder { 
    @Override 
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) { 
     char inChar = 0; 
     ChannelBuffer origBuffer = buf.copy(); 
     StringBuilder json = new StringBuilder(); 
     int ctr = 0; 
     while(buf.readable()) { 
      inChar = (char) buf.readByte(); 
      json.append(inChar); 
      if (inChar == '{') { 
       ctr++; 
      } else if (inChar == '}') { 
       ctr--; 
      } 
     } 
     if (json.length() > 0 && ctr == 0) { 
      return origBuffer; 
     } 
     buf.resetReaderIndex(); 
     return null; 
    } 
} 

(請原諒有點草率代碼 - 這是使用的Netty和我第一次嘗試的學習體驗一下。)

我看到發生什麼事是,這當我使用telnet,貼在一些有效的JSON然後按回車鍵連接到服務器上測試它工作正常。但是,如果我在JSON字符串中的最後一次關閉'}'之後沒有按回車,解碼器將不會被更新的緩衝區調用。

是否有配置通道管道的工作方式不同的方式?我已經爲此搜索並查看了Netty文檔。我覺得我錯過了一些基本的東西,我只是沒有找到正確的地方或尋找正確的東西。謝謝你的幫助。

+0

此外,我應該提到,這只是通過TCP套接字連接傳遞的原始JSON - 不涉及HTTP協議。 – 2013-03-22 16:59:42

回答

1

是您的Telnet客戶端恢復到模式的「老逐行」,從而只完成線發送到服務器(telnet man page)?嘗試編寫一個簡單的Java客戶端來發送消息。

+0

在這種情況下無關緊要。 FrameDecoder基類不會「中繼」消息,直到它看到整個幀(即讀新行) – 2013-03-23 13:07:27

+0

我不遵循。 FrameDecoder不知道幀是如何分隔的。在這個例子中,JsonDecoder確定在讀取框架時通過返回非null值,這通過匹配開啓和關閉大括號來確定。 ReplayingDecoder有助於此,但不是必需條件。我關於telnet'逐行'模式的觀點是,這會導致客戶端緩衝數據,直到輸入被按下。這似乎與它在客戶端斷開刷新客戶端緩衝區的情況下工作的事實相符。 – johnstlr 2013-03-25 08:51:34

+0

糟糕,你是對的。我錯誤地認爲使用了DelimiterBasedFrameDecoder。抱歉。 – 2013-03-25 21:59:10

1

我想讀一個JSON流更類似於讀取HTTP流,因爲你將不得不繼續跟蹤打開和關閉括號(和支架爲好,應該JSON字符串是一個數組)。如果您查看HTTP解碼器的源代碼,您會發現它使用的是ReplayingDecoder。使用重放解碼器不是必需的,但是如果整個消息被分割到多個緩衝區中,它會有很大的幫助。

FrameDecoders是指用於讀取由特殊字符「框架」的消息(解碼器由此得名)或具有長度字段前綴。

我也強烈建議使用DecoderEmbedder輔助類,這樣就可以單元測試你的JSON解碼器沒有做實際的I/O。

+0

謝謝!我會嘗試ReplayingDecoder - 我很樂觀,這將根據您的答案解決問題並更多地閱讀文檔。一旦我有機會嘗試它,請接受你的答案。 – 2013-03-23 17:56:10

+0

擴展ReplayingDecoder後我注意到的是解碼僅在客戶端斷開連接時才被調用。客戶端實際上會與服務器保持連接,並且在正常情況下不會斷開連接,所以我需要在正在進行的基礎上調用decode()。有沒有辦法用ReplayingDecoder做到這一點?或者我應該像IdleThreadHandler一樣使用ReplayingDecoder來以某種方式觸發緩衝區被讀取,如果在相當短的時間內沒有活動? – 2013-03-24 12:58:01

+0

只要接收緩衝區中有數據就調用decode()。其他事情正在發生;也許客戶端緩衝數據;很難說沒有更多的細節。 – 2013-03-24 16:26:59

相關問題