3

netty 4.0.24

I am passing XML over UDP. When receiving the UPD packet, the packet is always of length 2048, truncating the message. Even though, I have attempted to set the receive buffer size to something larger (4096, 8192, 65536) but it is not being honored.

I have verified the UDP sender using another UDP ingest mechanism. A standalone Java app using java.net.DatagramSocket. The XML is around 45k.

I was able to trace the stack to DatagramSocketImpl.createChannel (line 281). Stepping into DatagramChannelConfig, it has a receiveBufferSize of whatever I set (great), but a rcvBufAllocator of 2048.

Does the rcvBufAllocator override the receiveBufferSize (SO_RCVBUF)? Is the message coming in multiple buffers?

Any feedback or alternative solutions would be greatly appreciated.

I also should mention, I am using an ESB called vert.x which uses netty heavily. Since I was able to trace down to netty, I was hopeful that I could find help here.

Chris M
  • 31
  • 3

1 Answers1

4

The maximum size of incoming datagrams copied out of the socket is actually not a socket option, but rather a parameter of the socket read() function that your client passes in each time it wants to read a datagram. One advantage of this interface is that programs accepting datagrams of unknown/varying lengths can adaptively change the size of the memory allocated for incoming datagram copies such that they do not over-allocate memory while still getting the whole datagram. (In netty this allocation/prediction is done by implementors of io.netty.channel.RecvByteBufAllocator.)

In contrast, SO_RCVBUF is the size of a buffer that holds all of the datagrams your client hasn't read yet.

Here's an example of how to configure a UDP service with a fixed max incoming datagram size with netty 4.x using a 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();

You could also configure the allocator with ChannelConfig.setRecvByteBufAllocator

Mike Placentra
  • 835
  • 1
  • 14
  • 27
  • 1
    Just as a supplement. For UDP, `FixedRecvByteBufAllocator` is used as default and the default buffer size is 2048. – louxiu Apr 27 '16 at 13:36