我使用基于帧的解码器对netty管道进行单元测试。如果我使用的缓冲区大小小于最大帧,则看起来框架是不正确的。我正在使用包含两条消息的文件进行测试。长度字段是第二个工作,包括整个消息的长度,包括长度字段和前面的工作。
new LengthFieldBasedFrameDecoder(65536, 4, 4, -8, 0)
我正在阅读各种块大小的文件。第一条消息的大小为348字节,第二条消息的大小为456字节。如果使用512,335或更大的块大小,则读取这两个消息并将其正确地帧化到下一个处理程序,为了诊断目的,它将作为十六进制字符串打印出它接收的缓冲区的内容。如果使用较小的块大小,则会发生帧错误。用于读写文件的代码如下所示。
public class NCCTBinAToCSV {
private static String inputFileName = "/tmp/combined.bin";
private static final int BLOCKSIZE = 456;
public static void main(String[] args) throws Exception {
byte[] bytes = new byte[BLOCKSIZE];
EmbeddedChannel channel = new EmbeddedChannel(
new LengthFieldBasedFrameDecoder(65536, 4, 4, -8, 0),
new NCCTMessageDecoder(),
new StringOutputHandler());
FileInputStream fis = new FileInputStream(new File(inputFileName));
int bytesRead = 0;
while ((bytesRead = fis.read(bytes)) != -1) {
ByteBuf buf = Unpooled.wrappedBuffer(bytes, 0, bytesRead);
channel.writeInbound(buf);
}
channel.flush();
}
}
块大小为356字节的成功运行输出如下所示(为简洁起见,截断消息正文
LOG:DEBUG 2017-04-24 04:19:24,675[main](netty.NCCTMessageDecoder) - com.ticomgeo.mtr.ncct.netty.NCCTMessageDecoder.decode(NCCTMessageDecoder.java:21) ]received 348 bytes
Frame Start========================================
(byte) 0xbb, (byte) 0x55, (byte) 0x05, (byte) 0x16,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x5c,
(byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x50, (byte) 0x3a, (byte) 0xc9, (byte) 0x17,
....
Frame End========================================
Frame Start========================================
(byte) 0xbb, (byte) 0x55, (byte) 0x05, (byte) 0x1c,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xc8,
(byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x02,
(byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x04, (byte) 0x02, (byte) 0x00, (byte) 0x01,
如果我将块大小更改为256,则错误的字节似乎被读取为长度字段。
Exception in thread "main" io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 65536: 4294967040 - discarded
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:499)
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:477)
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:403)
答案 0 :(得分:3)
TL; DR;你的问题是由于netty重用传入的bytebuf,然后你覆盖了内容。
LengthFieldBasedFrameDecoder
是通过继承来设计的,以重用传入的ByteBuf
,因为当你可以重用它时,让对象通过垃圾回收来衰减是没用的,因为它的引用计数是1.然而问题是来自于您正在更改传入的bytebuf的内部,因此动态更改帧的事实。您应该使用wrappedBuffer
,而不是使用传入的变量作为存储使用copiedBuffer
,因为那个正确地复制了它,因此LengthFieldBasedFrameDecoder
的内部可以自由地执行用它做的事情。