búfer de corrupción en 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.

por ejemplo:

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

y

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?

preguntado el 09 de marzo de 12 a las 16:03

3 Respuestas

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

respondido 09 mar '12, 16:03

hi, thanks very much for the reply. Could you be more specific, e.g. how this happens and how to avoid? thx in advance. - user1259591

Only write to the output in one thread, or synchronize access to it. - pedro laurey

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.

respondido 18 mar '12, 14:03

Es el LengthFieldBasedFrameDecoder Se extiende 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 propiedad nombrada "cumulation",which will be shared to all Channels of the decoder.

and let's look inside the FrameDecoder.messageReceived método:

@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.

Respondido 04 Jul 12, 02:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.