2017-04-24 496 views
2

我正在使用基于帧的解码器测试netty管道。如果我使用比最大帧小的缓冲区大小,它看起来像框架是不正确的。我正在测试包含两条消息的文件。长度字段是第二件作品,包括整个消息的长度,包括长度字段和之前的作品。当缓冲区大小小于帧大小时,LengthFieldBasedFrameDecoder不能正确解析

new LengthFieldBasedFrameDecoder(65536, 4, 4, -8, 0) 

我正在读取具有各种块大小的文件。第一条消息的大小是348字节,第二条是456字节。如果使用512,346或更大的块大小,则同时读取两个消息,并将其正确地组帧到下一个处理程序,该程序出于诊断目的将以十六进制字符串的形式输出它接收到的缓冲区的内容。如果使用较小的块大小,则会出现组帧错误。下面显示了用于读取和写入文件的代码。从与356个字节块大小成功运行

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(); 
    } 
} 

输出低于显示(与消息体截断为简洁

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) 

回答

3

TL; DR;你的问题造成的,因为网状重用传入bytebuf,然后要覆盖内容

LengthFieldBasedFrameDecoder通过继承来重新设计传递的ByteBuf,因为通过垃圾回收使对象衰减是无用的,因为它的引用计数是1,所以可以重用它。然而,问题来自于您正在改变在bytebuf中传递的内部信息,因此可以即时改变帧。使用传入变量作为存储的wrappedBuffer(而不是制作wrappedBuffer)应该使用copiedBuffer,因为该编译器正确地创建了它的副本,因此LengthFieldBasedFrameDecoder的内部可以随意使用它。

+0

奇妙地工作。感谢您的帮助。 –

+0

不要忘记接受解决问题的答案,这标志着问题已解决,并允许其他在netty和java标记中处于活动状态的用户快速查看问题具有有效答案,您可以接受答案通过点击复选标记 – Ferrybig