Let's say I have a sender application and a receiver application that communicate via UDP.
First, in the sender application, I send some data in two separate calls. First I send these 15 bytes:
[MYHEADER]hello
...then, immediately thereafter, I send another 15 bytes:
[MYHEADER]world
Now, in the receiver application, I'm listening on the same port with a UDP socket that's bound to the same address. Let's say that both messages have arrived (and in the same order) since the last time I checked the receiver socket.
Here's some pseudo-code that shows how I'm polling the socket for incoming data each frame:
uint32 PendingSize;
while (Socket->HasPendingData(PendingSize))
{
uint32 BytesRead;
uint8 MessageData[kMaxMessageSize];
if (Socket->Recv(MessageData, kMaxMessageSize, BytesRead))
{
// Do stuff here
// Will BytesRead be equal to PendingSize?
}
}
HasPendingData
wraps a call to ioctlsocket
with FIONREAD
, returning whether data is waiting in the receive buffer, and populating PendingSize
with the number of bytes waiting. Recv
calls recv
to read that data into a buffer that I can read. If it returns true, then I respond to the data I've received.
Here's my question. Which of these scenarios accurately reflects what would happen in this situation?
Option A.
HasPendingData
returns true and shows a pending size of 15 bytes.Recv
gives me the message[MYHEADER]hello
.HasPendingData
returns true and shows a pending size of 15 bytes.Recv
gives me the message[MYHEADER]world
.HasPendingData
returns false.
Option B.
HasPendingData
returns true and shows a pending size of 30 bytes.Recv
gives me the message[MYHEADER]hello[MYHEADER]world
.HasPendingData
returns false.
Any insight is appreciated. Thanks!
UDP datagrams are individual and self-contained.
send()
andsendto()
send a new datagram each time.recv()
andrecvfrom()
read a single whole datagram. If your buffer is too small to receive a given datagram, you will get anWSAEMSGSIZE
error and that datagram will be lost if you do not specify theMSG_PEEK
flag.FIONREAD
tells you the total number of raw bytes in the socket's receive buffer, not the number of datagrams, or the size of those datagrams. This is clearly stated in the documentation:If you need to check the size of the next datagram, call
recv()
orrecvfrom()
with theMSG_PEEK
flag. Once you have deetermined the actual size of the datagram, you can read it without the flag so it is removed from the socket buffer. Otherwise, just allocate a buffer that is large enough to accommodate the largest datagram you will ever receive, or even just 65535 which is the largest size that UDP supports.So, to answer your question, what will really happen in your example is Option A, except that the first
HasPendingData
will report 30 pending bytes instead of 15.