简体   繁体   中英

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?

听起来您正在两个线程中写入同一流。

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM