Работа с фрагментацией в Netty

Я разрабатываю двоичный протокол для связи клиент/сервер с использованием Netty, и количество отправленных байтов не является фиксированным и может быть произвольным размером.

Клиент отправляет что-то вроде этого:

первые 4 байта представляют собой идентификационный номер, остальные байты представляют собой строку

В примере, который я видел, сообщение имеет фиксированный размер, но содержимое String может быть любого размера, и необходимо убедиться, что оно не фрагментировано при получении сервером. Как мне добиться этого в Netty?

Заранее спасибо.


person algolicious    schedule 18.01.2012    source источник


Ответы (2)


Как вы определяете конец сообщения? Ноль? Я бы проверил декодер воспроизведения Netty:

http://docs.jboss.org/netty/3.2/api/org/jboss/netty/handler/codec/replay/ReplayingDecoder.html

Это облегчает вам жизнь. Просто продолжайте читать, пока не найдете ноль. Если у вас закончатся байты до того, как вы достигнете нуля, будет выдано исключение для выхода из метода декодирования. Когда доступно больше байтов, метод декодирования будет вызываться снова с существующими байтами и новыми байтами, объединенными в один ChannelBuffer.

Этот цикл может повторяться до тех пор, пока у вас не будет всего сообщения в ChannelBuffer... которое затем вы сможете передать на следующий уровень для обработки.

Если бы можно было изменить ваш протокол, я бы добавил длину, поскольку возможность чтения по длине гораздо эффективнее, чем проверка каждого байта на наличие нуля.

person Gareth    schedule 18.01.2012
comment
Привет Гарет, спасибо за ответ - очень ценю. В настоящее время я ничего не использую для определения конца сообщения. Как только я получаю идентификатор, вызывая buffer.readLong(), я затем вызываю buffer.toString(String charsetName) - что не идеально. Когда вы имеете в виду отправку размера полезной нагрузки, вы предлагаете добавить его в начало и подождать, пока длина не будет получена, и использовать это произвольное число, чтобы определить, ждать ли на сервере больше байтов? - person algolicious; 19.01.2012
comment
да. Когда у вас есть длина, вы можете вместо этого использовать LengthFieldBasedFrameDecoder (если ваши сообщения, вероятно, будут очень большими, хотя, вероятно, лучше написать свой собственный на основе SimpleChannelUpstreamHandler, чтобы буфер выделялся только один раз). - person Gareth; 19.01.2012

Или, если он основан на строке, вы можете просто использовать DelimiterBasedFrameDecoder для задания.

См.: http://netty.io/docs/stable/api/org/jboss/netty/handler/codec/frame/DelimiterBasedFrameDecoder.html

person Norman Maurer    schedule 19.01.2012
comment
Спасибо! Похоже, мне нужно создать собственную реализацию FrameDecoder. - person algolicious; 19.01.2012