字节序

介绍大端、小端字节序的概念和内存布局差异,并解释为什么网络字节序统一采用大端,以及在 C 语言网络编程中如何通过 htons/ntohs/htonl/ntohl 进行主机字节序与网络字节序的转换。

post

Vitah Lin

2 min read
0

/

字节序,顾名思义就是字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据就无需谈顺序的问题),大部分人在实际的开发中很少会直接和字节序打交道。唯有在跨平台以及网络程序中才是一个应该被考虑的问题。

字节序分为两类

  • 大端字节序 Big-Endian
  • 小端字节序 Little-Endian

Little-Endian 就是低位字节放在内存的低地址端,高位字节排放在内存的高地址端。 Big-Endian 就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

高地址、低地址:内存的空间布局情况中,栈顶总是对应高地址,栈底总是对应低地址。

高位、低位:假设一个32位无符号整型 0x12345678,十进制中靠左边的是高位,靠右边的是低位,在其他进制也是如此。拿 0x12345678 来说,从高位到低位的字节依次是0x12,0x34,0x56,0x78。

我们以表格形式来表现 0x12345678 以不同方式在内存中存储的结构:

Big-Endian: 低地址存放高位Little-Endian: 低地址存放低位
栈顶 高地址栈顶 高地址
0x780x12
0x560x34
0x340x56
0x120x78
栈底 低地址栈底 低地址

由于只能从栈顶出栈、入栈,所以大端字节序存储形式可以看作:0x78563412,小端字节序存储形式是:0x12345678。

网络字节序:4个字节的32 bit 值以下面的次序传输:首先是0-7bit,其次是8-15bit,然后是16-23bit,最后是24-31bit。这种传输次序称作大端字节序。TCP/IP首部中的所有二进制整数在网络传输中都要求以这种次序,因为它又称作网络字节序。

既然网络字节序是大端字节序,那为什么会有小端字节序?而不是统一成大端字节序?

计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理大多都是小端字节序。
但是人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。
计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道顺序读区字节,先读第一个字节,再读第二个字节。
所以在网络编程中,需要调用函数来进行转换。

在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到 htons(), ntohl(), ntohs(),htons() 这4个函数。h 代表 host,n 代表 network,s 代表 short,l 代表 long。

  • htonl:Host to Network Long,把unsigned long类型从主机序转换到网络序
  • ntohl:Network to Host Long,把unsigned long类型从网络序转换到主机序
  • htons:Host to Network Short,将主机的无符号长整形数转换成网络字节顺序
  • ntohs:Network to Host Short,把unsigned short类型从网络序转换到主机序

Don't miss these

0
TCP发送缓冲区

Vitah Lin

·2 min read

0
TCP三次握手流程

Vitah Lin

·5 min read

0
计算机系统中的各种延时

Vitah Lin

·1 min read