Domanda

So in the case of TCP streams, one needs to keep track of how much is read of the message by each recv call. Partial reads can then be pieced together and ultimately the message can be received ok.

But for UDP messages, how should partial reads be handled (assuming that all UDP messages are small enough to avoid fragmentation)? As remaining data of partial messages seem to be discarded, is it just a matter of making sure that recvfrom returns the same size as the buffer that's been sent? If there is a difference it means it's a partial and defective message and it should be skipped.

So conceptually, while the TCP example needs a loop, the UDP example just needs an if statement.

Is this correct?

È stato utile?

Soluzione 3

correct. However that if condition will work only if receiver knows in advance how many bytes are being sent by the sender in advance.

Altri suggerimenti

It is not possible to do partial reads in UDP. UDP guarantees the datagram received is as was sent, fragmented or not, so must have received the entire datagram before you can read it.

See: http://en.wikipedia.org/wiki/User_Datagram_Protocol, you can follow the references in there for more official sources.

As for reading into a buffer you will need a buffer at least the size of any possible datagram. Or another common way is to include the size on the datagram near the beginning of the datagram so you can read only those bytes to get that number then use a buffer the appropriate size.

Incorrect. If recv() returns the same length it was given, the message was either that length or greater. There is no way of telling which. The correct technique is to use a buffer one greater than the largest possible datagram expected. Then if you get that length, it must have been an error on the sender's part.

As already mentioned, closely related to this question is the need for a strategy to pass a properly sized (large enough) buffer to recv/recvmsg/recvfrom when using these with datagram protocols. For UDP, a simple and 100% reliable method is to pass a buffer of at least 65507 bytes, the maximum UDP payload size.

However, a cleaner method that I prefer is to explicitly ask recv() how many bytes the buffer needs to be. This can be accomplished thusly:

int buflen = recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
if (buflen < 0) {
    // handle error
    return;
}
uint8_t buf[buflen];
rxlen = recv(sockfd, buf, buflen, 0);
if (rxlen < 0) {
    // again, handle error
    return;
}
// Voila!  We've received our entire datagram
// without need to know the maximum datagram
// size before runtime.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top