When acting on a UDP socket, what can cause
sendto() to send fewer bytes than requested?
The motivation for asking this is to figure out the precautions I need to take to ensure I always get a complete message sent in a single call to
sendto(), and to understand what further steps I need to take to get a message into a single IP packet. Do I just need to ensure my message is below some size, and if so, how big is that size? Besides OS-specific UDP datagram size limits and MTUs, are there other forces at work (e.g. i/o buffer capacities, capricious OSes)?
Having asked the principle question above, and in the title of this post, I'll continue with some related follow-on questions, and then put things into context at the end.
Going into more detail, again assuming we're acting on a UDP socket:
Does each successful call to
sendto()result in exactly 1 UDP datagram being sent? (I appreciate this may fragment into multiple IP packets)
Will each successful call to
recvfrom()retrieve exactly 1 UDP datagram?
If a single message takes N calls to
sendto()to send, will it take exactly N calls to
recvfrom()to receive, even if the receiving machine is a different platform? (I appreciate the datagram order will be unpredictable)
Suppose I attempt to send a message whose size is equal to or less than the smaller of the maximum UDP datagram sizes supported by the local and remote systems, (and baring some error which would result in a return value of -1) is
sendto()guaranteed to send my whole message in one go? Or might it report that it's sent fewer bytes than I've asked it to send? If so, why? Back to question 1.
In addition to the suppositions in question 4, supposing that my message is no bigger than the (MTU - UDP header - IP header) size, is the UDP datagram that results guaranteed to fit into 1 IP packet (on my local network at least)?
I've just started writing my first UDP-based communications protocol (cross platform: e.g. linux, mac, windows, ios, android, and more). I'm a socket newbie but am aware of the 'cost' that comes from using such a simple protocol as UDP and have researched algorithms/strategies for:
- Reliability and flow control
- Splitting big messages into multiple small ones
- Fountain codes to help compensate for some packet loss (by reducing resend requests).
- Encryption (see http ://srp.stanford.edu/)
I'm trying to break down all my communications into atomic messages (i.e. single, self-contained UDP datagrams) which might (but not necessarily) be required to fit into a single IP packet (e.g. 1500bytes). Real-time assessment of throughput and packet-loss will determine if I have to shrink datagrams to fit into single IP packets (this would incur a size penalty from additional headers). Some of this will be over wifi/radio links, so I'm hoping to determine the 'optimal' datagram size adaptively. I know the MTU of all my interfaces, and appreciate that outside my local network things packets may get split further, but that's out of my control, so I can live with it.
But everything hinges on being able to construct an atomic message and have 100% confidence that I can send it successfully with a single call to
sendto(), and receive if with a single call to
recvfrom(). All my application-level reliability, splitting, encoding and encryption information lives in my own protocol header, and I can't re-split messages after a call to
sendto() comes back short. E.g. think of a message checksum: if the whole message doesn't get through in one go, the checksum in the header is no longer valid for the portion of the message that has been sent.