Question

While receiving the integer array, checking the bytes of data received is needed. For example, when receiving an integer array with length 100:

int count = 0;
int msg[100];
while(count < 100 * sizeof(int)){
    count += read(fd, msg + count / sizeof(int), 100 * sizeof(int) - count);
}

Is this a right way? Will read() return a value which is not a multiple of sizeof(int)? If this is not correct, what the right way to receive an integer array?

Was it helpful?

Solution

On Linux you can use the MSG_WAITALL option for recv(), which makes the function wait for the full given length of incoming data.

In alternative (working on all platforms) you can also write a generic receive function that receives a given amount of bytes, like this one (which assumes the socket is not set as non-blocking; requires including <stdint.h>):

/// \brief Receives a block of data of the specified size
/// \param sk Socket for incoming data
/// \param data Pointer to input buffer
/// \param len Number of bytes to read
/// \return Number of bytes received (same as len) on success, -1 on failure
int block_recv(const int sk, uint8_t* data, unsigned int len)
{
    int i, j = 0;

    while (len > 0) {
        i = recv(sk, (char*) data, len, 0);
        if (i <= 0) {
            return -1;
        }
        data += i;
        len -= i;
        j += i;
    }

    return j;
}

Then you can just call it to receive your integer buffer:

if (block_recv(fd, (uint8_t*) msg, sizeof(msg)) != sizeof(msg)) {
    fprintf(stderr, "Error receiving integer buffer...\n");
    // whatever error handling you need...
}

OTHER TIPS

You are correct that read may not return all the data you requested, esp. if it is connected to a network socket. read will not necessarily return a value with multiple of sizeof(int). If you want to use this (manual) method of receiving data, I would probably recommend you count bytes instead of sizeof(int)s (which can be 4 or 8 depending on your system). Even easier than doing this is to use something like Protocol Buffers, which lets you define a data format for your packets and serialize/deserialize them quickly and easily. (Define a message that simply includes your integer array and let protobuf take care of everything else.)

You're right - there's no guarantee that read will return data whose size is a multiple of sizeof(int). The minimum size you may receive is a char. There are other issues such as endianness when receiving integers from across a network (which obviously also apply to sending integers across a network) that you should be aware of.

For these reasons, an easier solution is to use a char[] instead of int[] to store the message, and then copy it to an int[]. If you are concerned about efficiency, prove to yourself that this is a bottleneck (profile your code) before you worry about optimizing code.

Also, if you are sending and recving across a network, be aware that protocols like TCP are stream-based, i.e. they simply send streams of characters and you need to implement some way of detecting the end of a message and formatting it to your needs. Two common ways are to either send the length of the message as a header or to use a special character like '\n' to signal the end of the message. Also, since you are sending an array, you could use something like '|' to separate elements.

So a sample message can be: "1|100|239|23|\n"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top