缓冲区网络腐败

时间:2012-03-09 16:24:28

标签: java netty

使用netty(使用camel)时出现了一个奇怪的错误,我们使用LengthFieldBasedFrameDecoder进行通信,client是来自第三方的套接字程序,我们在服务器端使用netty(camel-netty组件)。

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

例如:

客户端发送两条消息:

[10] AAAAAAAAAAAAAAAA 和 [10] BBBBBBBBBBBBBBBB

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

但在我们得到的服务器上 [10] AAAAAA [10] BBBBBBBBBBBBBBBBAAAAAAAAAA

似乎第一条消息被第二条消息拆分,因此解码器将数据解释为:

[10] AAAAAA [10] BBBBBBBB

BBBBBBBBAAAAAAAAAA .............................................. .....

这样第一条消息的长度正确但数据错误,第二条消息长度为“BB”错误,并获得更长的数据包。

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

3 个答案:

答案 0 :(得分:2)

听起来你正在用两个线程写同一个流。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

您的LengthFieldBasedFrameDecoder是否延伸FrameDecoder? 是单身还是不单身?

实际上我解决了同样的问题,我同意彼得的观点;

我查看了FrameDecoder,发现有一个名为“累积”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的正确方法是将其设为多个。