Skip to content
Advertisement

Can I be sure that a UDP recv executed immediately after a successfull call to recv with MSG_PEEK will not block?

Assume the following code (for the sake of simplicity I’ve omitted the necessary error handling here):

recv(sockfd, NULL, 0, MSG_PEEK);
recv(sockfd, buff, bufflen, 0);

In that case: Can I be sure that after the first call to recv the whole datagram is already received and therefore the second call to to recv will not block?

Or can it happen that if IP splits the datagram, the first recv returns as soon as any part of this datagram is received, and the second recv will block until the whole datagram is received?

If I substitute the first call to recv with:

recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);

Can I be sure that this will only return once the whole datagram is received, since otherwise it would be no way for recv to reliably return the length of the whole datagram, as requested by MSG_TRUNC?

Advertisement

Answer

Can I be sure that after the first call to recv the whole datagram is already received and therefore the second call to to recv will not block?

A UDP socket operates in whole-datagram units. The first call will not return until a datagram is available, unless it returns -1 to indicate an error. (A TCP socket might return 0 to signal closure of the connection, but that will not happen with a UDP, since it’s connectionless.)

@Barmar observes in comments that another thread or processwith access to the same socket could, in principle, read that waiting datagram before the one that called the first recv() does, but if that’s not a concern for you then the subsequent recv() indeed should return the whole datagram, up to the amount of space available in the buffer (any excess bytes in the message are lost). Of course this begs the question of why you want to do this — you might as well have skipped the first recv(), and let the second one block if necessary.

Adding MSG_TRUNC to the flags doesn’t alter any of the above. Again, a UDP socket operates in whole-datagram units. The only difference is that the return value gives you the size of the datagram. That could be a reason for the extra recv() call.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement