在网络通信过程中。获取数据时,我们要根据目标设备的cpu和编译器模式,统一大小端模式使收发数据一致。

大端和小端模式

我们假设计算机使用16位二进制存储数字258,其采用大端模式存储时,我们以8位为一个字节,其内存结构如图所示。

大端模式取得数据时:
按字节排序,依次取得字节按照2进制解析取得数据,如这里先取得第一个字节00000001
将这个数1x2^8,得到256,再取得第二字节00000010,将这个数1x2^1,得到2,256+2=258。
如果使用小端模式来存储:

小端模式取得数据时:
从最后字节依次向前取值,例如这里则先解析第二个字节,再解析第一个字节。

  • 大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

  • 小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

cpu体系结构

常用的x86体系结构使用的是小端结构,很多ARM,DSP都为小端模式,但KEIL C51等为大端模式。有些ARM处理器可自己切换模式,市面上有些手机使用大端模式,有些手机使用小端模式。为了做到兼容,我们要考虑到大小端问题。

在Csharp中解决大小端问题

其实在csharp中BitConverter下的转换方法已经能够自动判断系统的大小端类型做对应处理,但是我们还是有必要了解处理过程。

方法一:使用Linq翻转序列

var len = (Int16)258;
var bytes = BitConverter.GetBytes(len);
if (!BitConverter.IsLittleEndian)
{
    //大端->小端
    bytes.Reverse();    //翻转序列
}

方法二:使用指针操作

对于16位存储,我们可以直接将第二字节左移8位与第一字节做|运算即可。

var data = (short)bytes[1] << 8 | bytes[0];