views:

512

answers:

2

I am working on a UDP server built with boost::asio and I started from the tutorial customizing to my needs. When I call socket.receive_from(boost::asio::buffer(buf), remote, 0, error); it fills my buffer with data from the packet, but, if my understanding is correct, it drops any data that won't fit in the buffer. Subsequent calls to receive_from will receive the next datagram available, so it looks to me like there is some loss of data without even a notice. Am I understanding this the wrong way?

I tried reading over and over the boost::asio documentation, but I didn't manage to find clues as to how I am supposed to do this the right way. What I'd like to do is reading a certain amount of data so that I can process it; if reading an entire datagram is the only way, I can manage that, but then how can I be sure not to lose the data I am receiving? What buffer size should I use to be sure? Is there any way to tell that my buffer is too small and I'm losing information?

I have to assume that I may be receiving huge datagrams by design.

+2  A: 

This is not specific to boost; it's just how datagram sockets work. You have to specify the buffer size, and if the packet doesn't fit into the buffer, then it will be truncated and there is no way to recover the lost information.

For example, the SNMP protocol specifies that:

An implementation of this protocol need not accept messages whose length exceeds 484 octets. However, it is recommended that implementations support larger datagrams whenever feasible.

In short: you have to take it into account when designing your communication protocol that datagrams may be lost, or they may be truncated beyond some specified size.

andri
That is what I thought and I just needed confirmation from someone with more experience on this issue. I talked with the project manager and he gave me an estimate of the maximum size of the datagrams, although there is no fixed protocol.
Kjir
A: 

Use getsockopt with the SO_NREAD option.

From the Mac OS X manpage:

SO_NREAD returns the amount of data in the input buffer that is available to be received. For data-gram oriented sockets, SO_NREAD returns the size of the first packet -- this differs from the ioctl() command FIONREAD that returns the total amount of data available.

Zan Lynx
There is an available() method in the boost::asio::ip::udp::socket class, thanks for the suggestion.
Kjir