ReceiveBufferSize не соблюдается. UDP-пакет усечен

нетти 4.0.24

Я передаю XML через UDP. При получении пакета UPD длина пакета всегда составляет 2048, что усекает сообщение. Несмотря на то, что я попытался установить размер буфера приема на что-то большее (4096, 8192, 65536), но он не соблюдается.

Я проверил отправителя UDP, используя другой механизм приема UDP. Автономное приложение Java, использующее java.net.DatagramSocket. XML составляет около 45k.

Мне удалось отследить стек до DatagramSocketImpl.createChannel (строка 281). Вступая в DatagramChannelConfig, он имеет ReceiveBufferSize того, что я установил (отлично), но rcvBufAllocator 2048.

rcvBufAllocator переопределяет ReceiveBufferSize (SO_RCVBUF)? Сообщение поступает в несколько буферов?

Будем очень признательны за любые отзывы или альтернативные решения.

Я также должен упомянуть, что я использую ESB под названием vert.x, который интенсивно использует netty. Поскольку мне удалось проследить путь до Нетти, я надеялся, что смогу найти здесь помощь.


person Chris M    schedule 22.01.2015    source источник


Ответы (1)


Максимальный размер входящих дейтаграмм, скопированных из сокета, на самом деле не параметр сокета, а скорее параметр функции сокета read(), которую ваш клиент передает каждый раз, когда он хочет прочитать дейтаграмму. Одним из преимуществ этого интерфейса является то, что программы, принимающие дейтаграммы неизвестной/переменной длины, могут адаптивно изменять размер памяти, выделенной для копий входящих дейтаграмм, так, чтобы они не перераспределяли память, но при этом получали всю дейтаграмму. (В netty это распределение/прогнозирование выполняется разработчиками io.netty.channel.RecvByteBufAllocator.)

Напротив, SO_RCVBUF — это размер буфера, который содержит все дейтаграммы, которые ваш клиент еще не прочитал.

Вот пример того, как настроить службу UDP с фиксированным максимальным размером входящей дейтаграммы с помощью netty 4.x с использованием Bootstrap:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;

int maxDatagramSize = 4092;
String bindAddr = "0.0.0.0";
int port = 1234;

SimpleChannelInboundHandler<DatagramPacket> handler = . . .;
InetSocketAddress address = new InetSocketAddress(bindAddr, port);
NioEventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap()
      .group(group)
      .channel(NioDatagramChannel.class)
      .handler(handler);
b.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(maxDatagramSize));
b.bind(address).sync().channel().closeFuture().await();

Вы также можете настроить распределитель с помощью ChannelConfig.setRecvByteBufAllocator

person Mike Placentra    schedule 17.09.2015
comment
Просто как доп. Для UDP по умолчанию используется FixedRecvByteBufAllocator, а размер буфера по умолчанию равен 2048. - person louxiu; 27.04.2016