Networking & Sockets

network byte order and htons/ntohl

/ htons -> aitch-tee-en-ESS, ntohl -> en-tee-oh-ELL /

Different computers disagree about which end of a multi-byte number to write first. Some store the number 0x12345678 starting with 0x12 (big-endian), others starting with 0x78 (little-endian). That is fine inside one machine, but on a network two machines that disagree would read each other's numbers backwards. So the internet picked one convention - big-endian - for numbers travelling on the wire, called network byte order, and gives you small functions to convert to and from it.

The rule: any multi-byte number you put into a packet header - most importantly a port number and an IP address - must be in network byte order (big-endian) before it goes out, and converted back to your machine's order (host byte order) when it comes in. The conversion functions are named for size and direction: htons() = host-to-network-short (16-bit, used for ports), htonl() = host-to-network-long (32-bit, used for IPv4 addresses), and ntohs()/ntohl() do the reverse, network-to-host. On a big-endian machine these are no-ops; on a little-endian machine (like most x86 laptops) they swap the bytes. You call them blindly either way, and your code stays correct on both.

Why it matters: forget this and your code may work perfectly between two identical machines and then mysteriously fail talking to a different one - a port 80 sent without htons() arrives as port 20480. It is one of the few places in socket programming where you must consciously convert, because the numbers cross a boundary between machines that may store bytes differently. The fix is mechanical: wrap every port and address number in htons()/htonl() on the way out and ntohs()/ntohl() on the way in.

addr.sin_port = htons(8080); converts the port 8080 from your machine's order into big-endian for the wire. On the way back, int port = ntohs(addr.sin_port); converts it back so you can print or compare it. Call them even if you are unsure - they are correct no-ops on a big-endian host.

htons/htonl on the way out, ntohs/ntohl on the way in - mechanical, and correct on every machine.

The byte string of an IP or the bytes of your message payload are not numbers and must not be passed through these functions - only multi-byte integer header fields like ports and IPv4 addresses need conversion.

Also called
big-endian on the wirebyte order conversion網路位元組序大端序