Netty 5.0.0: байты из неполного фрейма отбрасываются

Я пишу декодер-обработчик для двоичного формата сообщения, который можно декодировать до последнего полного элемента сообщения в доступных байтах. Итак, если есть массив значений int64, вы читаете максимальное число, кратное 8 байтам, которое меньше ByteBuf.readableBytes(). Я использую netty 5.0.0.Alpha2.

Моя проблема в том, что похоже, что Netty отбрасывает непрочитанные байты, оставшиеся в ByteBuf, а не добавляет к ним новые сетевые байты; это означает, что когда я пытаюсь возобновить декодирование, происходит сбой, так как отсутствуют байты и поврежден поток.

Существуют ли методы ChannelHandlerContext, ByteBuf или Channel, которые я должен использовать для сохранения этих непрочитанных байтов? Или текущее/единственное решение сохранить их в пустом пространстве внутри обработчика самостоятельно? Я подозреваю, что буферный пул является причиной того, что для последующего чтения используется другой буфер.

Спасибо

Майкл

PS: я не заинтересован в использовании классов ReplayingDecoder или ByteToMessageDecoder, так как подгонка под них моей библиотеки декодера была бы слишком навязчивой (ИМХО).


person Michael_73    schedule 11.04.2015    source источник
comment
какова длина рамы, которую вы ожидаете?   -  person HCarrasko    schedule 11.04.2015
comment
Он варьируется, но может быть до 2 ГБ.   -  person Michael_73    schedule 11.04.2015
comment
Я думаю, что мог бы решить эту проблему, .retain перейдя к ByteBuf, если в нем все еще есть читаемые байты, и сохранив его дескриптор до следующего чтения, а затем обернув его и новый ByteBuf в составной буфер. Я напишу что-нибудь в какой-то момент, если кто-то не придумает лучший ответ;)   -  person Michael_73    schedule 11.04.2015


Ответы (1)


Существуют ли методы ChannelHandlerContext или ByteBuf или Channel, которые я должен вызывать для сохранения этих непрочитанных байтов? Или текущее/единственное решение сохранить их в пустом пространстве внутри обработчика самостоятельно? Я подозреваю, что буферный пул является причиной того, что для последующего чтения используется другой буфер.

Это то, что делает ByteToMessageDecoder. Если я правильно понял, вы хотите, чтобы ваш буфер всегда имел n * 8 байт.

public class Int64ListDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ctx, in, out) {
        final int inLen = in.readableBytes();
        final int outLen = inLen / 8 * 8;
        out.add(in.readSlice(outLen).retain());
    }
}
person trustin    schedule 12.04.2015
comment
Привет Trustin, спасибо за ваш ответ. Я видел ByteToMessageDecoder, но, поскольку сообщение может иметь размер до 2 ГБ, декодер специально разработан для возобновляемости и поддержки оконного чтения. Дело в том, что я должен быть в состоянии прочитать сообщение размером 2 ГБ в любом заданном (разумном) размере фрагмента, используя буфер чтения, скажем, 256 КБ. (1/2) - person Michael_73; 13.04.2015
comment
Первоначальный вопрос касается того, что делать с непрочитанными байтами, оставшимися в буфере в конце частичного чтения, которые не могут быть кратны восьми - это был просто пример, иллюстрирующий, как байты могут вообще оставаться непрочитанными. Существуют разные типы данных, в частности строковые типы, которые имеют разную длину: например, это char-vec value.length(). (2/2) - person Michael_73; 13.04.2015
comment
Я понимаю. Тогда вам придется реализовать некий конечный автомат. В зависимости от сложности протокола он может быть немного запутанным. Пожалуйста, взгляните на HttpObjectDecoder для примера. Однако вы можете реализовать декодер без использования ByteToMessageDecoder. - person trustin; 16.04.2015