Search code examples
csocketsint

transfer integer over a socket in C


What is the appropriate way to transfer an int over a socket in C?
What I am doing so far is:

int n = 4;
int tmp = htonl(n);
write(socket, &tmp, sizeof(tmp));

and

int tmp,n;
read(socket, &tmp, sizeof(tmp));
n = ntohl(tmp);

However, the integer received is sometimes 0. Not always, but let's say 2 out of 5 times. It is never some other value, always 0. Why?

UPDATE: Return value from read is -1 and an error is:

Resource temporarily unavailable

Solution

  • First of all, sizeof(int) may differ on your sender and receiver machine. So I would recommend you to use something like int32_t from stdint.h.

    Also, it is not guaranteed that read(..,..,sizeof(int)) will read exactly sizeof(int) bytes - it can read nothing, or it can read less bytes. So, the correct variant will be something more like this:

    int send_int(int num, int fd)
    {
        int32_t conv = htonl(num);
        char *data = (char*)&conv;
        int left = sizeof(conv);
        int rc;
        do {
            rc = write(fd, data, left);
            if (rc < 0) {
                if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                    // use select() or epoll() to wait for the socket to be writable again
                }
                else if (errno != EINTR) {
                    return -1;
                }
            }
            else {
                data += rc;
                left -= rc;
            }
        }
        while (left > 0);
        return 0;
    }
    
    int receive_int(int *num, int fd)
    {
        int32_t ret;
        char *data = (char*)&ret;
        int left = sizeof(ret);
        int rc;
        do {
            rc = read(fd, data, left);
            if (rc <= 0) { /* instead of ret */
                if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                    // use select() or epoll() to wait for the socket to be readable again
                }
                else if (errno != EINTR) {
                    return -1;
                }
            }
            else {
                data += rc;
                left -= rc;
            }
        }
        while (left > 0);
        *num = ntohl(ret);
        return 0;
    }