Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

transfer integer over a socket in C

Tags:

c

int

sockets

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
like image 324
Maggie Avatar asked Feb 04 '12 11:02

Maggie


People also ask

How do you send an integer value into a socket?

tcpsocket. send(num) accept a string , link to the api, so don't convert the number you insert to int . Show activity on this post. If you send the number 11 and then immediately send 12, how will the receiver know whether you sent two numbers: 11 and 12 or one number: 1112?

What is socket () in C?

DESCRIPTION. The socket() function shall create an unbound socket in a communications domain, and return a file descriptor that can be used in later function calls that operate on sockets. The socket() function takes the following arguments: domain. Specifies the communications domain in which a socket is to be created ...

Why is a socket an integer?

All that matters in your code is that the number represents a specific file or socket. The integer that's returned by socket() is a file descriptor, i.e. a value that refers to a specific FILE data structure.

Can sockets send and receive both?

You can send and recv from any connected socket. The direction of the data flow does not have anything to do with the client/server relationship. It is very common for clients and servers to both send and receive.


1 Answers

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;
}
like image 142
Borisko Avatar answered Oct 03 '22 03:10

Borisko