当前位置: 动力学知识库 > 问答 > 编程问答 >

java - buffer corruption in netty

问题描述:

I got a strange error when using netty(with camel), we use LengthFieldBasedFrameDecoder for communication, client is a socket program from third party, we use netty(camel-netty component) on the server side.

sometimes got two messages "merged" into one, and hence the forthcoming data get all wrong.

for example:

client send two messages:

[10]AAAAAAAAAAAAAAAA

and

[10]BBBBBBBBBBBBBBBB

where [10] is the length bytes and AAAAAAAAAA is the data.

but on the server we got

[10]AAAAAA[10]BBBBBBBBBBBBBBBBAAAAAAAAAA

seems the the first message got split by the second one, so the decoder interpreted the data as:

[10]AAAAAA[10]BBBBBBBB

and

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

so that the first message is correct in length but wrong in data, and the second message is wrong in length "BB", and get a much longer data packet.

hope I described clearly, anyone met this before?

网友答案:

It sounds like you are writing to the same stream in two threads.

网友答案:

well, this proved to be a "bug" of camel-netty component, I will post a fix to camel project later on. Before that, please be careful using the camel-netty component, especially do not use encoders/decoders not mark with @sharable annotation, it will lead to the problem since state maybe shared among different connections.

网友答案:

Is your LengthFieldBasedFrameDecoder extends FrameDecoder? And is it singleton or not?

Actually I encounted the same problem,and I agree with Peter's point;

I've took a look at the FrameDecoder,and found that there is a ChannelBuffer property named "cumulation",which will be shared to all Channels of the decoder.

and let's look inside the FrameDecoder.messageReceived method:

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

I think the correct way to use FrameDecoder is make it multcase.

分享给朋友:
您可能感兴趣的文章:
随机阅读: