Sending data in "network byte order" (which is big-endian) and conversion "must take a place" is biggest lie network tutorials are selling you on the internet.
Data send over network DOES NOT CARE in what endian they are. They are just bytes. Whatever you'll send it, you will receive it in same order.
Only place where endianness matters is IP packet headers, so if you're writing network drivers or special firewall rules, then yeah you sometimes care about endianness. But for regular API usage you DO NOT CARE which endianness you use. So simply use whatever is simpler for you.
If you know that your code will always run on little endian machine (which is probably close to 100% of your actual use cases) then you simply read and write it same way and that's it. It'll work.
u16 send_msg = 0xBEEF;
write(server_fd, &send_msg, sizeof(send_msg));
...
u16 recv_msg;
read(client_fd, &recv_msg, sizeof(recv_msg));
and recv_msg will be 0xBEEF. Simple as that.
Or alternatively you can serialize variables to values in endian independent way. So they will be read and written the same regardless if sender is big endian, or receiver little endian, or other way around. This code will work the same in all situations:
u16 send_msg = 0xBEEF;
u8 bytes[2];
bytes[0] = (u8)(send_msg >> 0);
bytes[1] = (u8)(send_msg >> 8);
write(server_fd, bytes, sizeof(bytes));
...
u8 bytes[2];
read(client_fd, bytes, sizeof(bytes));
u16 recv_msg = (u16)((bytes[0] << 0) | (bytes[1] << 8));
Other way to think about all of this is to pretend that write/read is just memcpy
. Then exactly same logic applies. With your example:
u16 msg2 = 0xBEEF;
char recv_buf[2];
memcpy(recv_buf, msg2, sizeof(msg2)); // replace write/read with memcpy
// now recv_buf = { 0xEF, 0xBE };
No networking involved, just exactly same bytes are copied around.