I am attempting to send a integer over the network in C (more specifically, uint32_t
bytes). I believe I am sending the data correctly, according to other examples and answers on Stack Overflow; however, when receiving the bytes, I am having trouble casting/converting them to uint32_t
. Here is an example of my attempt:
Sender:
uint32_t num = htonl(100);
char* converted_num = (char*)#
send(client_sock, converted_num, sizeof(num), 0);
Receiver:
char buf[8192];
recv(socket, buf, 8192, 0);
uint32_t test = ntohl((uint32_t)&buf);
printf("%d\n", (int)test);
The receiver outputs a large integer 1755042816
and not the correct integer value "100". What am I doing wrong?
You're casting a pointer to an integer which won't work.
*(uint32_t*)&buf
might work if you're lucky, but it's undefined-behavior C due to a strict aliasing violation.
To be correct, you should first memcpy
to an uin32_t
and then apply nthol
to that.
static inline uint32_t ntohl_ch(char const *X)
{
uint32_t x; memcpy(&x,X,sizeof(x));
return ntohl(x);
}
//...
uint32_t test = ntohl_ch(&buf[0]);
//...
Strict aliasing allows you to treat any object as an array of char
(or signed char
or unsigned char
). The reverse is not true. Imagining an uint32_t
in an array of char
is not allowed and you must use memcpy
.
Optimizing compilers will notice you're memcpy
'ing just an uint32_t
and elide a full memcpy
call (in favor of a direct mov to register or a direct application of a an assembly instruction on the original memory).