大端模式,是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;小端模式,是指数据的高位保存在内存的高地址中,而数 据的低位保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
其他地方看到一种说法:
在创建socket的时候或者bind的时候需要htons来转换字节序,而以后在send函数发送data的时候却不需要转换了呢?我想会不会是:底层协议进行了转换,但是在创建的时候学要转换一下来“握手”,在“达成共识”以后由协议(底层程序)来完成这个工作。
但实际上这种说法并不正确.
验证如下:
建立好socket连接之后,
在小端模式下,发送数据0x12345678
通过wireshark抓包发现得到的数据为78562312,在接收端按字符接收并按字符打印为78563412
在大端模式下,发送数据0x12345678
通过wireshark抓包发现得到的数据为12345678,在接收端按字符接收并按字符打印为12345678
如果send、recv进行了字节序的转换,在小端模式下wireshark 抓包结果应该为12345678才正确。
实际上send、recv与字节序没有任何关系,发送的数据只是按照其参数(即字符数组)进行发送和接收的,在小端模式下,首先发送低地址的数据,在大端模式下,首先发送高地址的数据(通过wireshark抓包可以看出数据发送的顺序)。
位域与字节序的关系:
在对struct中的成员进行分配的时候,"按排列顺序分配,先分配排在前面的" (参考网上资料)
1)big endian从高位向低位分配,
a. 对字节,是先分配低地址的字节,再分配高地址的字节。
b. 对位域,先分配高地址,再分配低地址。
1)little endian从低位向高位分配,
a. 对字节,是先分配低地址的字节,再分配高地址的字节。
b. 对位域,先分配低地址,再分配高地址。
因此对于结构体数据,小端地址定义如下:
struct yaabou_com{
union
{
struct
{
unsigned int a: 4,
b: 4,
c: 4,
d: 4,
e: 16;
}pack;
unsigned int uiRaw; /*用来获取全部内容*/
}header;
};
如果大端模式下需要定义与上相同的结构体,则定义如下:
struct yaabou_com{
union
{
struct
{
unsigned int e: 4,
d: 4,
c: 4,
b: 4,
a: 16;
}pack;
unsigned int uiRaw; /*用来获取全部内容*/
}header;
};
必须要进行字节序的转换。
所以对结构体中的位操作时,需要对大小端进行区分并单独定义。
对结构体yaabou_com定义为a = 1,b=2,c=4,d=8,e = 16.
小端模式下,利用send发送结构体数据时,wireshark抓包为21841000(先分配低地址,最终uiRaw的值为0x00108421,send按照低地址进行发送后得到0x21841000)
大端模式下,利用send发送结构体数据时,wireshark抓包为12480010(先分配高地址,最终uiRaw的值为0x12480010.send按高地址发送得到0x12480010)