# 网络字节序

字节序(Endian)：分为大端字节序和小端字节序。

> “endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开，由此曾发生过六次叛乱，其中一个皇帝送了命，另一个丢了王位。

大端字节序（Big Endian） ：最高有效位（MSB：Most significant Bit）存储于最低内存地址处。最低有效位（LSB：Lowest significant Bit）存储于最高内存地址处。

小端字节序（Little Endian） ：最高有效位（MSB：Most significant Bit）存储于最高内存地址处。最低有效位（LSB：Lowest significant Bit）存储于最低内存地址处。

## 举例![](https://313308022-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LfnT30T9rtIVtc5eWQf%2F-LfnT9dAhhstiSPRKKVD%2F-LfnTGQ1-2LkXcZiZ6V9%2Fendian.jpg?generation=1558862979694306\&alt=media)

> 注意 0x12345678 是一个16进制的地址，表示一个内存地址。占四个字节。
>
> 为什么占4个字节？
>
> 1个字节是8位,最多表示0到256
>
> 而一位16最多只表示到16,即F表示16,要表示到256,就还需要第二位,
>
> 所以1个字节占2个16进制位
>
> 一个16进制位占0.5个字节

## 为什么要统一字节序？引入字节序的概念？

因为socket它能够实现异构系统间通信，不同的硬件平台，对这样一个整数它的存放\
形式是不一样的，有的机器它采用的是大端字节序，有的机器它采用的是小端字节序\
来进行存放，那么这样一个数字如果传输至对等方时，对等方就无法解析了，特别是\
字节序不同，解析出来的数据就会相反，这时候就得统一字节序，将这些数据传输的时候\
统一成一个字节序，那么统一出来字节序我们把他称为是**网络字节序**，**这个网络字节序规定**\
**的是大端字节序。**

![](https://313308022-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LfnT30T9rtIVtc5eWQf%2F-LfnT9dAhhstiSPRKKVD%2F-LfnTGQ3hVFa5DzU2cxn%2Fendian_eg.jpg?generation=1558862960952985\&alt=media)

那我们要传输这样一个整数的时候呢，就需要将主机上面的字节序（有可能是大端字节序，也有\
可能是小端字节序），

如图：假定A就是大端字节序，假定B就是小端字节序

假设主机A 传输数据到主机B，主机A先要将字节序转换成网络字节序，到达B端时候\
又要将网络字节序转换成主机字节序。

那么A它转换成网络字节序的时候是不需要进行调整的，直接传输\
接下来，网络字节序转换成B主机的字节序，那么就需要把它颠倒过来（因为网络字节序是大端字节序，而B主机是小端字节序）\
这样B才能正确解析出来整数。

## 检测是小端字节序还是大端字节序？

c语言

```c
#include <stdio.h>

int main(void){
    unsigned int x = 0x12345678;
    unsigned char *p  = (unsigned char*)&x;
    printf("%0x_%0x_%0x_%0x\n", p[0], p[1], p[2], p[3]);
    return 0;
}
```

输出结果：

```
78_56_34_12
```

## 资料

[Big Endian和Little Endian的区别](http://blog.chinaunix.net/uid-479984-id-2114895.html)

[网络通信之 字节序转换原理与网络字节序、大端和小端模式](http://www.cnblogs.com/fuchongjundream/p/3914770.html)
