Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

non-blocking udp socket programming in C: what do I get?

I have a problem in understanding what recv()/recvfrom() return from an non-blockig UDP socket.

A bit more specific and compared to TCP (please correct me if I'm wrong):

  • A blocking socket (either TCP or UDP) won't return from a recv() until there is some data in the buffer. This could be some number of bytes (TCP) or a complete datagram (UDP).

  • A non-blocking TCP socket either returns EWOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) or the bytes that are currently in the buffer. As TCP data is a stream it doesn't matter how many bytes are returned.

Now the question:

  • A non-blocking UDP socket also returns WOULDBLOCK (linux) / WSAEWOULDBLOCK (windows) if there is no data available. But if there is data availabe, does a non-blocking UDP socket return just some bytes, which could mean you only get half of a datagram OR does an UDP socket always return complete datagrams??

Edit:

What I mean with "half of a datagram" is: what happens if I call recv() in just the moment when the socket is currently receiving a datagram. In that moment there are some bytes in the buffer but the datagram isn't complete yet.

Your explanations and comments are appreciated. Thanks!

like image 289
Uwe Avatar asked Feb 10 '10 20:02

Uwe


2 Answers

Finally, an excuse to dig out my Stevens books from my old office boxes.

Provided the buffer is large enough, the standard Berkeley sockets recv() and recvfrom() functions will never return a partial datagram. The datagram is not available to the application until the kernel has completely received and reassembled the datagram.

Interestingly, and this isn't much (any?) of an issue today, other network programming interfaces don't agree on the behavior when the provided buffer is too small:

The traditional Berkeley version of the sockets API truncates the datagram, discarding any excess data. Whether the application is notified depends on the version. (4.3BSD Reno and later can notify the application that the datagram was truncated.)

The sockets API under SVR4 (including Solaris 2.x) does not truncate the datagram. Any excess data is returned in subsequent reads. The application is not notified that multiple reads are being fulfilled from a single UDP datagram.

The TLI API does not discard the data. Instead a flag is returned indicating that more data is available, and subsequent reads by the application return the rest of the datagram.

(Stevens, TCP/IP Illustrated, Volume 1, p. 160)

like image 55
Steve Madsen Avatar answered Sep 18 '22 02:09

Steve Madsen


Yes, UDP just returns what data got transmitted in that one datagram. UDP is not stream-oriented like TCP. Datagrams are discrete transmissions, and are not really tied to other datagrams in any way. That's the reason the socket option for TCP is SOCK_STREAM.

The bright side of this is that you can get a sense of separate transmissions, which isn't really easy to do with TCP.

like image 29
T.E.D. Avatar answered Sep 20 '22 02:09

T.E.D.