主机字节序和网络字节序

主机字节序

主机字节序是指在特定计算机系统中数据的存储顺序。常见的字节序有两种:

  • 大端字节序(Big-endian): 数据的高字节存储在低地址端。例如,数值 0x12345678 将按顺序存储为 0x12 0x34 0x56 0x78
  • 小端字节序(Little-endian): 数据的低字节存储在低地址端。例如,数值 0x12345678 将按顺序存储为 0x78 0x56 0x34 0x12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main(int argc, char* argv[]) {

int num = 0x61626364; // abcd

// 大端 : 0x61626364 --》 abcd

// 小端 : 0x64636261 --》 dcba

char* str = (char*)# // 将num的地址转为char*类型,逐字节检查;如果是 a,大端;如果是 d,小端

if (*str == 'd') { // 检查最低字节
printf("小端\n");
}
else if (*str == 'a') {
printf("大端\n");
}

return 0;
}

核心还是取到一个可识别的字节对应的内容,一般取 int 类型数据的地址,转换为 char* 代表第一个字节(从左往右看)。因此,也可以有如下代码,原理相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main() {
unsigned int num = 1; // 定义一个整数
char *byte = reinterpret_cast<char*>(&num); // 将整数的地址转换为字符指针

if (byte[0] == 1) {
std::cout << "小端字节序" << std::endl; // 如果最低位字节在最前面,说明是小端
} else {
std::cout << "大端字节序" << std::endl; // 如果最高位字节在最前面,说明是大端
}

return 0;
}

网络字节序

网络字节序是一种标准化的数据表示方式,用于在不同计算机系统之间传输数据。为了确保数据在网络传输中保持一致,网络协议(如 TCP/IP)规定采用大端字节序

主机字节序和网络字节序的转换

htons(Host to Network Short):将 16 位主机字节序转换为网络字节序

htonl(Host to Network Long):将 32 位主机字节序转换为网络字节序

ntohs(Network to Host Short):将 16 位网络字节序转换为主机字节序

ntohl(Network to Host Long):将 32 位网络字节序转换为主机字节序

在网络编程中,数据收发的过程中有自动转换机制,不需要程序员手动转换,只有向 sockadd_in 结构体成员变量填充数据时,才需要考虑字节序的问题

1
2
3
4
5
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port); // 端口号转换为网络字节序
server_addr.sin_addr.s_addr = inet_addr(ip.c_str());

sockaddr_in 结构体成员 sin_port 接受 16位的大端序,因此用 htons 处理端口 port

inet_addr 函数已经返回了网络字节序(big-endian)的地址,也就用不着 htonl 处理网络地址 ip