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

妖精的绣舞 提交于 2019-12-06 23:11:35

问题


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!


回答1:


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)




回答2:


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.




回答3:


I believe you get precisely one or zero datagrams. But I can't back this up at this moment. Perhaps someone else could provide a good reference?

Edit: I'm pretty sure you can't receive half a datagram. Either the datagram has arrived in the in buffer, or it hasn't.



来源:https://stackoverflow.com/questions/2239986/non-blocking-udp-socket-programming-in-c-what-do-i-get

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!