netty中的缓冲区损坏



我在使用netty(带camel)时遇到了一个奇怪的错误,我们使用LengthFieldBasedFrameDecoder进行通信,客户端是来自第三方的套接字程序,我们在服务器端使用netty。

有时会将两条消息"合并"为一条消息,因此即将发布的数据都是错误的。

例如:

客户端发送两条消息:

[10] aaaaaaaaaa和[10] bbbbbbbbbb

其中[10]是长度字节,AAAAAAAAAA是数据。

但在服务器上[10] aaaaa[10]bbbbbbbbbb

似乎第一条消息被第二条消息分割了,所以解码器将数据解释为:

[10] aaaaa[10]BBBBBBBB-

BBBBBBBBAAAAAAAAAA。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

使得第一条消息长度正确但数据错误,第二条消息长度"BB"错误,并获得更长的数据包。

希望我描述清楚,以前有人见过这个吗?

听起来像是在两个线程中对同一个流进行写入。

好吧,这被证明是camel-nety组件的一个"bug",我稍后会发布对camel-netti项目的修复。在此之前,请小心使用camel-netty组件,特别是不要使用没有用@sharable注释标记的编码器/解码器,这会导致问题,因为状态可能在不同的连接之间共享。

您的LengthFieldBasedFrameDecoder是否扩展了FrameDecoder?它是单身还是单身?

事实上,我也遇到了同样的问题,我同意彼得的观点;

我查看了FrameDecoder,发现有一个名为"cumulation"ChannelBuffer属性,它将共享给解码器的所有通道。

让我们看看FrameDecoder.messageReceived方法内部:

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    Object m = e.getMessage();
    if (!(m instanceof ChannelBuffer)) {
        ctx.sendUpstream(e);
        return;
    }
    ChannelBuffer input = (ChannelBuffer) m; // here is the buffer from the channel
    if (!input.readable()) {
        return;
    }
    ChannelBuffer cumulation = cumulation(ctx); // here is the buffer wrapped by the FrameDecoder
    if (cumulation.readable()) {
        cumulation.discardReadBytes();
        // where "[10]AAA[10]BBBBB" happens
        cumulation.writeBytes(input); 
        // if code run here,we will get the wrong buffer
        callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
    } else {
        callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
        if (input.readable()) {
            cumulation.writeBytes(input);
        }
    }
}

我认为使用FrameDecoder的正确方法是使其成为多个实例。