最近在为Tokyo Tyrant写一个.NET客户端类库。Tokyo Tyrant公开了一个基于 TCP协议的二进制协议,于是我们的工作其实也只是按照协议发送和读取一些二进 制数据流而已,并不麻烦。不过在其中涉及到了 “字节序”的概念,这本是计算 机体系结构/操作系统等课程的基础,不过我还是打算在这里进行简单说明,并且 对.NET中部分类库在此类数据流处理时的注意事项进行些许记录与总结。
字节序(Byte Order)
说到程序间的通信,说到底便是发送数据流。我们一般把字节(byte)看作是 数据的最小单位。当然,其实一个字节中还包含8个比特(bit)──有时候我奇 怪为什么很多朋友会不知道bit或是它和byte的关系。当我们拿到一系列byte的时 候,它本身其实是没有意义的,有意义的只是“识别字节的方式”。例如,同样4 个字节的数据,我们可以把它看作是1个 32位整数、2个Unicode、或者字符4个 ASCII字符。
同样我们知道,在一个32位的 CPU中“字长”为32个bit,也就是4个byte。在 这样的CPU中,总是以4字节对齐的方式来读取或写入内存,那么同样这4个字节的 数据是以什么顺序保存在内存中的呢?例如,现在我们要向内存地址为a的地方写 入数据0x0A0B0C0D,那么这4个字节分别落在哪个地址的内存上呢?这就涉及到字 节序的问题了。
每个数据都有所谓的“有效位(significant byte)”,它的意思是“表示这 个数据所用的字节”。例如一个32位整数,它的有效位就是4个字节。而对于 0x0A0B0C0D来说,它的有效位从高到低便是0A、0B、0C及0D——这里您可以把它 作为一个256进制的数来看(相对于我们平时所用的10进制数)。
而所谓大字节序(big endian),便是指其“最高有效位(most significant byte)”落在低地址上的存储方式。例如像地址a写入0x0A0B0C0D之后,在内存中 的数据便是: