我使用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