Sockets: Internet Domains 1199
However, we sometimes make direct use of integer constants for IP addresses
and port numbers. For example, we may choose to hard-code a port number into
our program, specify a port number as a command-line argument to a program, or
use constants such as INADDR_ANY and INADDR_LOOPBACK when specifying an IPv4
address. These values are represented in C according to the conventions of the
host machine, so they are in host byte order. We must convert these values to net-
work byte order before storing them in socket address structures.
The htons(), htonl(), ntohs(), and ntohl() functions are defined (typically as macros)
for converting integers in either direction between host and network byte order.
In earlier times, these functions had prototypes such as the following:
unsigned long htonl(unsigned long hostlong);
This reveals the origin of the function names—in this case, host to network long. On
most early systems on which sockets were implemented, short integers were 16 bits,
and long integers were 32 bits. This no longer holds true on modern systems (at
least for long integers), so the prototypes given above provide a more exact definition
of the types dealt with by these functions, although the names remain unchanged.
The uint16_t and uint32_t data types are 16-bit and 32-bit unsigned integers.
Strictly speaking, the use of these four functions is necessary only on systems
where the host byte order differs from network byte order. However, these func-
tions should always be used, so that programs are portable to different hardware
architectures. On systems where the host byte order is the same as network byte
order, these functions simply return their arguments unchanged.
59.3 Data Representation
When writing network programs, we need to be aware of the fact that different
computer architectures use different conventions for representing various data
types. We have already noted that integer types can be stored in big-endian or little-
endian form. There are also other possible differences. For example, the C long
data type may be 32 bits on some systems and 64 bits on others. When we consider
structures, the issue is further complicated by the fact that different implementations
#include <arpa/inet.h>
uint16_t htons(uint16_t host_uint16);
Returns host_uint16 converted to network byte order
uint32_t htonl(uint32_t host_uint32);
Returns host_uint32 converted to network byte order
uint16_t ntohs(uint16_t net_uint16);
Returns net_uint16 converted to host byte order
uint32_t ntohl(uint32_t net_uint32);
Returns net_uint32 converted to host byte order