网络序?本地序?傻傻分不清楚。。。
这个问题源于最近做的一个项目,需要用Node.js进行socket网络编程,涉及到使用TCP/UDP通过自定义的二进制数据序列化协议与android/iOS客户端进行通信。
当协商通信协议时,对接的客户端同学告诉我在发送数据的时候要将要发送的Buffer从本地序转换为网络序,当收到客户端的回包时,需要将收到的Buffer从网络序转换为本地序。
作为一个前端工程师,听到上面那段话,我脑海中的画面是:
网络序?本地序?傻傻分不清楚啊!
于是我决定翻开下面这本书,来一探究竟:
什么是网络序和本地序?
所谓的网络序和本地序其实就是一个跨越多个字节的程序对象(在Node.js中可以简单的认为是一个长度大于1的Buffer对象)在存储器中的存储顺序,在了解这两种字节顺序之前,我们来复习一下计算机的寻址规则。
寻址
在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址,毕竟位(bit)所能表示的信息太有限了(0 or 1)。例如,假设一个类型为int的变量x的地址为0x100,也就是说,地址表达式&x的值为0x100。那么,x的4个字节将被存储在存储器的0x100、0x101、0x102和0x103的位置。
字节顺序规则
在存储器中如何排列一个跨越多个字节的程序对象,一般来说有两个通用的规则。
考虑一个w位(bit)的整数,位表示为[xw-1, xw-2, … ,x1, x0],其中xw-1是最高有效位,而x0是最低有效位。假设w是8的倍数,这些位就能被分组成为字节,其中最高有效字节包含位[xw-1, xw-2, … ,xw-8],而最低有效字节包含位[x7, x6, … ,xw-8],其他字节包含中间的位。某些机器选择在存储器中按照从最低有效字节到最高有效字节的顺序存储对象,而另一些机器则按照从最高有效字节到最低有效字节的顺序存储。前一种规则——最低有效字节在最前面的方式,称为小端法(little endian)。大多数Inter兼容机都采用这种规则。后一种规则——最高有效位在最前面的方式,称为大端法(big endian)。大多数IBM和Sun Microsystems的机器都采用这种规则。(注: IBM和Sun制造的个人计算机使用的是Inter兼容的处理器,这些机器采用的是小端法)
许多比较新的微处理器使用双端法(bi-endian),也就是说可以把它们配置成作为大端或者小端的机器运行。大家先记住小端法(little endian)和大端法(big endian)这两个名词,这对于我们理解网络序和本地序灰常重要。
继续我们前面的示例,假设变量x类型为int,占四个字节,位于地址0x100,它的十六进制值为0x1234567。地址的范围为0x100~0x103的字节,其排列顺序依赖与机器的类型。
大端法:
字节存储地址 | 0x100 | 0x100 | 0x100 | 0x100 | ||
---|---|---|---|---|---|---|
字节内容 | … | 01 | 23 | 45 | 67 | … |
小端法:
字节存储地址 | 0x100 | 0x100 | 0x100 | 0x100 |
---|