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
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;
}