Netty 4.01 CR6 的偶发性 OutOfBounds 问题

Sparodic OutOfBounds issue with Netty 4.01 CR6

我开发的自定义解码器有问题,我不确定自己做错了什么。

我们收到的消息格式包含HEADER、BODY和TRAILER。 header 是 1 个字节,是一个 STX (0x02) body 是可变长度 尾部是 2 个字节,包含一个 ETX(0x03),后跟一个 LRC。

所以典型的消息可能如下所示:

STX   BODY   ETX  LRC
02  37000000 06   18

解码器的输出应该是没有STX控制字节的消息。所以发送的消息是:

BODY     ETX  LRC
37000000 06   18

我们扩展了 DelimiterBasedFrameDecoder 并将 ETX 定义为分隔符。解码器的目的是读取下一个字节,将其添加到缓冲区然后继续发送,这样我们就可以发送完整的消息。我们的解码方法如下所示:

protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
    Object frame = super.decode(ctx, buffer);

    if (frame == null) {
        return null;
    }
    ByteBuf msg = null;

    if (frame instanceof ByteBuf) {
        msg = Unpooled.copiedBuffer((ByteBuf) frame);
        msg.writeByte(buffer.readByte());
        ((ByteBuf) frame).release();
    }

    while (msg.getByte(0) != STX) {
        msg.readByte();
        msg = msg.discardReadBytes();
    }

    return msg;
}

一切都按预期工作,除了我们会定期收到以下异常。

java.lang.IndexOutOfBoundsException: readerIndex(225) + length(1) exceeds writerIndex(225): UnpooledUnsafeDirectByteBuf(ridx: 225, widx: 225, cap: 256)

我们正在使用 Netty 4.01 CR6,这是一个偶发问题。我不确定的是,这是我做的不正确,还是 Netty 内部的问题。由于我是 Netty 的新手,我怀疑这是我正在做的事情,但我不确定。

我希望有人能帮我解决这个问题。我很乐意 post 更多信息来解决这个问题,请问。

感谢我能在这方面得到的所有帮助。

此异常意味着您正试图从 bytebuf 中读取一个它不包含的字节,因为您已到达它的末尾。

客户端发送了无效数据,或者您的协议中并非所有数据包都在消息中包含 STX

解码现有协议时常犯的另一个错误是,您用作定界符的字节序列在数据包本身内部使用,并且您应该逐字节读取数据包。

如果你想看到数据包流向你的解码器,你可以添加一个 LoggingHandler(LogLevel.INFO) 到管道,就在你的解码器 运行 之前,所以它会打印出原始字节作为十六进制,因此您可以检查它是否确实包含所需的字节序列。

旁注:你永远不会释放存储在msg中的bytebuf。这将造成内存泄漏并最终导致 OOM,确保在 try-finally 块中调用 release,因此它总是被调用