Keeto
Keeto

Reputation: 4198

Reading the maximum size of an expected packet from a C socket

I have a client/server program. The client sends a message to the server and the server processes this message and gets back to the client.

The first four bytes of the client message is the size of the whole message. I also know the maximum size a message can be. However, messages are of variable sizes.

I am using the read function in a while loop to read the client messages

while((n = read(socket, buffer, MAX_SIZE)) != 0){
    process_message();
    write(socket, ...);
}

I was wondering if there is any harm in reading more bytes than what the client is sending? I can first read the size of the message and then read the exact number of bytes but I was wondering if this is necessary.

Upvotes: 2

Views: 1167

Answers (1)

n1000
n1000

Reputation: 132

As mentioned in some other comments, reading from a socket can return any number of bytes, up to the maximum requested.

A better loop, although still not without problems, would be something along these lines:

/* 4 byte message header that contains the length */
#define MSG_HEADER_SIZE 4
#define MAX_MESSAGE_LENGTH 128
struct message {
    uint32_t length;
    char body[MAX_MESSAGE_LENGTH];
};

#define BUFFER_SIZE 1024
char buffer[BUFFER_SIZE];
uint32_t buf_used = 0;

/* main loop */
while (1) {
    n = recv(socket, buffer + buf_used, sizeof(buffer) - buf_used, 0);

    if (n == -1) {
        /* handle error */
        exit(1);
    }

    if (n == 0) {
        /* connection closed, do something. */
        exit(1);
    }

    buf_used += n;

    /* check for partial/completed message(s) */
    while (buf_used >= MSG_HEADER_SIZE) {
        struct message *cur_msg = (struct message *) buffer;
        uint32_t total_msg_length;

        total_msg_length = cur_msg->length + MSG_HEADER_SIZE;

        /* is this message completed yet? */
        if (buf_used >= total_msg_length) {
            process_message(cur_msg);

            /* remove message since it has been processed */
            buf_used -= total_msg_length;

            /* this could potentially be optimized */
            memmove(buffer, buffer + total_msg_length, buf_used);
        } else {
            /* have incomplete message */
            break;
        }
    }
}

For an introduction to socket programming, I would recommend checking out Beej's Guide to Network Programming.

Upvotes: 2

Related Questions