MSG_WAITALL and all that

Anyone who has done much socket programming knows that UDP preserves message boundaries, but TCP does not.  While TCP guarantees that the blob received  will be identical to the blob that was sent, the individual writes performed by the sender will not necessarily result in the recipient reading the same number of messages.  Put another way, TCP is a stream protocol, while UDP is a record protocol.

As a result, anyone who has had to cobble up his or her own protocol that uses TCP as the transport protocol has probably written code that

  1. reads a fixed length header, which may require multiple reads,
  2. extracts a message length from the header, perhaps converting it from network to host order,
  3. reads a message of the desired length, perhaps with multiple reads.

Pseudo code for the “multiple reads” is

int msg_ln = DESIRED_LN;
for ( ; ; )
{
    int readCount = recv(sockfd, buff, msg_ln, 0);
    if (readCount < 1 || readCount <= msg_ln)
    (
        break;
    }
    msg_ln -= readCount;
}

I.e, keep reading until you get the expected number of characters.

That was then, this is now. The Linux recv function now has the option MSG_WAITALL, which blocks until an expected number of bytes is received or until the socket closes. So the above code would  be replaced by

int msg_ln = DESIRED_LN;
int readCount = recv(sockfd, buff, msg_ln, MSG_WAITALL);

This is a nice convenience option. It’s nothing you could not write on your own, but it’s a good thing to de-clutter your code.

See my Github project, MSG_WAITALL, for a working example.

 

Advertisements

One thought on “MSG_WAITALL and all that

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s