I am working on a reliable file transfer program that uses UDP. (for a course in computer networking.)
My question is this - well, consider this scenario:
Sender has (for example) 12 bytes of data to send. So the sender performs this call:
sendto(fd, &buf, 12, 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
This sends the 12 bytes of data in an unreliable way. The first 4 bytes of this data happens to be a "message length" field. In this case, the first 4 bytes might have the value 0x0000000C
The receiver wants to read the first 4 bytes using recvfrom(). Seeing that the segment size is 12 bytes, it wants to read the remaining 8 bytes. So the receiver might look like this:
/* read the segment size */ recvfrom(sockfd,&buf,4,0,(struct sockaddr *)&cliaddr,&len); /* do some arithmetic, use bzero(), etc */ /* read the rest of the data */ recvfrom(sockfd,&buf,8,0,(struct sockaddr *)&cliaddr,&len);
When I execute this code, I can receive the first 4 bytes without a problem. But when I try to fetch the remaining data, that data seems to be lost. In my output, I'm getting garbage - it looks like some portion of the next 12 bytes that the sender is sendto()-ing.
Is this expected behavior? That is to say, if a single recvfrom() call does not read all of the data that was sent, is it not guaranteed that that data (the remaining 8 bytes) is available to me?
It seems like the standard method of sending a segment header (including its size), followed by the payload, does not work. Does that mean that I need to send 2 separate segments - one that only contains header information, and then a 2nd segment with the payload? Or am I just using these syscalls incorrectly (or is there a flag or setsockopt() that I'm missing?)