网络字节序

字节序

字节序：存放字节的顺序。

字节序与 CPU 架构相关，通常 x86 架构使用小端序，字节序决定数据在内存中存储的顺序。

在网络通信传输数据时需要统一字节序，以确保能够正常的传输和解析数据。

存储数据方式有：大端序（Big-Endian）和 小端序（Little-Endian）。

大端序：高位字节存储在低地址，低位字节存储在高地址（低对高）。

小端序：高位字节存储在高地址，低位字节存储在低地址（低对低）。

对于 0x1234 十六进制的数，12 是高位字节，34 是低位字节。而高地址和低地址指的是地址的大小，例如有两个地址 0x1010 和 0x1011，0x1010 就是低地址，0x1011 就是高地址。

判断本机字节序

Copy
// 1 Byte = 8 bit（8 位二进制代表一个字节）
// 1 位十六进制代表 4 bit
// short 占 2 Byte = 16 bit
// char 占 1 Byte = 8 bit
// 强转为 char *，后取出的首地址（低位地址）占 1 Byte
// 将这个低位地址解引用后转为 short
// 与原始数据中的低位和高位进行比较
// 如果等于高位则说明为大端序（低对高）
// 如果等于低位则说明为小端序（低对低）

// 如果是大端序，低地址存储数据的高位字节
// 高位字节是 0x12
// &i 取出的是低地址
// (short)*(char *)&i == 0x12
bool isBigEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x12;
}

// 如果是小端序，低地址存储数据的低位字节
// 低位字节是 0x34
// &i 取出的是低地址
// (short)*(char *)&i == 0x34
bool isLittleEndian() {
short i = 0x1234;
return (short)*(char *)&i == 0x34;
}

简单写法：

Copy
bool isBigEndian() {
short i = 1;
return *(char *)&i != 1;
}

转换本机字节序与网络字节序

网络字节序通常使用大端字节序。

POSIX API

Copy
// host to network unsigned short
htons();

// host to network unsigned long
htonl();

// network to host unsigned short
ntohs();

// network to host unsigned long
ntohl();

Boost Asio API

Copy
// host to network unsigned short
boost::asio::detail::socket_ops::host_to_network_short();

// host to network unsigned long
boost::asio::detail::socket_ops::host_to_network_long();

// network to host unsigned short
boost::asio::detail::socket_ops::network_to_host_short();

// network to host unsigned long
boost::asio::detail::socket_ops::network_to_host_long();

在使用这些 API 时，应该确保输入参数和返回结果都是无符号整型，否则可能存在符号拓展问题。