我使用EmbeddedChannel
來測試我的handlers
和codecs
在下面的格式處理消息:的Netty ByteToMessageCodec <ByteBuf>解碼消息兩次(部分)
+------------+------------------+----------------+
| Header | Payload Length | Payload |
| 16 bytes | 2 bytes | "Some data" |
+------------+------------------+----------------+
首先,我想達到的目標:
- 通過創建一個對象來存儲標題詳細信息並將解碼後的標題對象添加到
ChannelHandlerContext
的AttributeMap
中以供將來使用; - 等待/檢索整個有效載荷數據;
- 將Header對象和整個有效載荷作爲
ByteBuf
用於路由消息的最終處理程序。
我使用以下處理:
ByteToMessageCodec<ByteBuf>
提取頭信息,並將其添加到屬性列表。LengthFieldBasedFrameDecoder
讀取有效載荷長度並等待/檢索整個幀。SimpleChannelInboundHandler
這將使用從屬性列表檢索到的頭對象相應地路由有效載荷。
當一個消息被傳遞給ByteToMessageCodec
的decode
方法,所述報頭處理和正確地提取。然後,我繼續將頭對象添加到AttributeMap
並添加ByteBuf
(其有一個可讀字節= 2字節(有效負載長度指示符)+有效負載長度)。
假設有效載荷長度是1020字節。該消息最初由codec
收到,將有readableBytes = 16 bytes + 2 bytes + 1020 bytes
。通過decode
方法讀取頭部,然後將餘下的可用字節(1022)添加到List<Object> out
。
如果我的理解是正確的,該字節的其餘部分將現在被傳遞到下一個處理是LengthFieldBasedFrameDecoder
將讀取的長度指標和有效載荷(1020個字節)傳遞給SimpleChannelHanlder
,但我一定是搞錯了。
decode
方法被稱爲再次,與List<Object> out
相同的1022字節。
在解碼方法那裏的JavaDoc如下:
Decode the from one ByteBuf to an other. This method will be called till either the input ByteBuf
has nothing to read when return from this method or till nothing was read from the input ByteBuf.
這是否意味着decode
將被調用,直到readableBytes == 0
?
將其餘消息傳遞給LengthFieldBasedFrameDecoder
的最有效方法是什麼?
我承擔LengthFieldBasedFrameDecoder
需要ByteBuf
作爲輸入,所以這是否意味着我需要設置readerIndex = 0
和ByteBuf的副本添加到List<Object> out
?
任何幫助/建議/批評將不勝感激,我想以最乾淨的方式做到這一點。
這裏是我的decode
方法:
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
byte [] headerBytes = new byte[HEADER_LENGTH];
in.readBytes(headerBytes, 0, HEADER_LENGTH);
Header header = new Header(headerBytes);
System.out.println("Decoded Header: \n" + header);
//Set the header attribute so it can be used by routing handlers
ctx.attr(ChannelAttributes.HEADER).getAndSet(header);
//pass to next handler
out.add(in);
}
謝謝! 'setSingleDecode(true)'正是我所需要的。但是我似乎無法在實現'ByteToMessageCodec'時找到方法,只有'ByteToMessageDecoder'。無論如何,將分解編碼和解碼過程。並感謝有關將'header'傳遞給下一個處理程序的提示。然而,我通過執行'ctx.channel()。attr(ChannelAttributes.HEADER).set(header)'來設置和檢索'header',並將它添加到頻道的'AttributeMap'中。這樣做有什麼缺點? – Ian2thedv 2014-10-29 07:33:05
啊,是的,'setSingleDecode'只存在於'ByteToMessageDecoder'上。至於頻道上的屬性地圖,我沒有看到任何缺點,這當然是一個可行的解決方案。 – knutwalker 2014-10-29 08:56:32