当缓冲区大小小于帧大小

时间:2017-04-24 15:28:13

标签: java netty

我使用基于帧的解码器对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)

1 个答案:

答案 0 :(得分:3)

TL; DR;你的问题是由于netty重用传入的bytebuf,然后你覆盖了内容。

LengthFieldBasedFrameDecoder是通过继承来设计的,以重用传入的ByteBuf,因为当你可以重用它时,让对象通过垃圾回收来衰减是没用的,因为它的引用计数是1.然而问题是来自于您正在更改传入的bytebuf的内部,因此动态更改帧的事实。您应该使用wrappedBuffer,而不是使用传入的变量作为存储使用copiedBuffer,因为那个正确地复制了它,因此LengthFieldBasedFrameDecoder的内部可以自由地执行用它做的事情。