本人才疏学浅有不恰当的或者错误的个人观点,还望指出共同进步。
小说下网络字节序与主机字节序:看是简单的问题其实内在的东西还是不少的,由于不同的计算机系统采用不同的字节序存储数据,同样一个 4 字节的 32 位整数,在内存中存储的方式就不同。字节序分为小端字节序 (Little Endian) 也就是我们常见的主机字节序和大端字节序 (Big Endian) 指的就是网络字节序了 , Intel 处理器大多数使用小端字节序 (Little Endian), Motorola 处理器大多数使用大端 (Big Endian) 字节序。小端就是低位字节排放在内存的低端,高位字节排放在内存的高端。大端就是高位字节排放在内存的低端,低位字节排放在内存的高端。说到这里也需你会感觉有些模糊,下面让我们通过一个简单的例子说明他们之间的差别与存在的意义。文章以下内容将小端字节序用主机字节序表示,大端字节序使用网络字节序代替。
首先我们在网络编程时,一般都要把主机字节序转换成网络字节序,这是为什么呢? TCP/IP 各层协议将字节序定义为大端,例如,在一个 TCP 分节中,有一个 16 位的端口号和一个 32 为的 IPV4 地址,发送协议栈和接收协议栈必须对此多字节字段的传送字节序进行协调,以达成一致。网际协议在处理这些多字节整数时,使用大端字节序。所以当我们使用 bind 、 lesson 、 recv 、 send 等函数时需要为他们指出套接口地址结构,而该结构中的 IP 地址及 PORT 号是网络字节序的。
先让我们从字面理解下字节序的概念,主机字节序与网络字节序,所谓的字节序应该是以 1 个字节为单位进行的一种字节序列化操作,接下来让我们看看主机字节序与网络字节序在内存中的状态:
例如一个 2 字节的值为 0x81 的整数其十进制为 2049
主机字节序内存状态:
15 0xF1 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 0xF0 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
网络字节序内存状态:
0 0xF0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 0xF1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
这里明显看出只是按照字节 ( 也就是 8 位 ) 的顺序颠倒,而不是位的倒序。 OK 了解了网络字节序与主机字节序的区别后我们也可以写出 ntohi 、 ntohl 、 htoni 、 ntonl 的函数实现了。并且当是 64 位、 128 位的网络字节序转换成主机字节序对于我们来说也不是问题了。