повреждение буфера в netty

Я получил странную ошибку при использовании netty (с верблюдом), мы используем LengthFieldBasedFrameDecoder для связи, клиент - это программа сокетов от стороннего производителя, мы используем netty (компонент верблюда-нетти) на стороне сервера.

иногда два сообщения «сливались» в одно, и, следовательно, предстоящие данные были неверными.

Например:

клиент отправляет два сообщения:

[10]ААААААААААААААА и [10]БББББББББББББ

где [10] — длина байтов, а AAAAAAAAAA — данные.

но на сервере мы получили [10]AAAAAA[10]BBBBBBBBBBBBBBBBAAAAAAAAAAAA

кажется, что первое сообщение было разделено вторым, поэтому декодер интерпретировал данные как:

[10]АААААА[10]БББББББ

и

ББББББАААААААААААААААААААААА................................ ..

так что первое сообщение имеет правильную длину, но неверные данные, а второе сообщение имеет неправильную длину «BB», и получают гораздо более длинный пакет данных.

надеюсь понятно описал, кто-нибудь встречал такое раньше?


person user1259591    schedule 09.03.2012    source источник


Ответы (3)


Похоже, вы пишете в один и тот же поток в двух потоках.

person Peter Lawrey    schedule 09.03.2012
comment
привет, большое спасибо за ответ. Не могли бы вы быть более конкретным, например. как это происходит и как избежать? Спасибо заранее. - person user1259591; 09.03.2012
comment
Записывайте вывод только в одном потоке или синхронизируйте доступ к нему. - person Peter Lawrey; 09.03.2012

что ж, это оказалось «ошибкой» компонента camel-netty, позже я опубликую исправление для проекта camel. Перед этим, пожалуйста, будьте осторожны при использовании компонента camel-netty, особенно не используйте кодировщики/декодеры, не отмеченные аннотацией @sharable, это приведет к проблеме, поскольку состояние может распределяться между разными соединениями.

person user1259591    schedule 18.03.2012

Ваш 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 - сделать его многократным.

person Robb Tsang    schedule 04.07.2012