c语言把网络字节序转换成小端,网络编程字节序转换问题

一:大小端

(一)大小端区别(字节)

区别是依据:计算机系统在存储数据时起始地址是高地址仍是低地址。

03861a65fced2073fca614187b1fc65b.png

小端:从低地址开始存储

b0a621dfc297faa5d96b248fbbb9de58.png

大端:从高地址开始存储

56d84ad2f2cf9b7332ae85603d139bb6.png

补充:这里大小端是按字节区别的,还有按字的。按字节,则字节大小数据不会改变数据格式,因此如上图中小端“1”,和大端“1”是同样存储的

补充:在内存中存储数据仍是从低地址开始寻址,找到一块空间分配之后,根据大小端区别向内部填充数据

(二)代码实现对大小端的判断

#include #include

using namespacestd;boolbigCheck()

{

union Check{//起始地址是一致的

chara;

uint32_t data;

};

Check c;

c.data= 1;if(1==c.a){return false;

}return true;

}int main(int argc,char*argv[])

{if(bigCheck()){

cout<

}else{

cout<

}return 0;

}

1.选取内存空间

d2a95788bd6fa1d9d13849c572301a72.png

2.大端存放数据

46bad4c3329d33fbbcc8e549b94ee347.png

3.小端存放数据

7cfaae43038dd79be110dc2bb6645742.png

输出结果:

84f3085ff554188467ad16ae3726b049.png

二:本地系统与网络中的大小端问题

(一)本地操做系统与网络字节序

1.本地字节序

不一样操做系统可能会采用不一样的字节序,因此当通讯双方字节序不一样时须要考虑字节序转化问题ios

2.网络字节序

为了不在网络通讯中引入其余复杂性,网络字节序统一是大端的编程

(二)序列化与反序列化

任何变量,无论是堆变量仍是栈变量都对应着操做系统中的一块内存,因为内存对齐的要求程序中的变量并非紧凑存储的,例如一个c语言的结构体Test在内存中的布局可能以下图所示。网络

eeef163de8ff387b4843a95fa68382b9.png

1.序列化:经过将计算机语言中的内存对象转换为网络字节流,例如把c语言中的结构体Test转化成uint8_t data[6]字节流。

89e359dedf183cb983b8f9142dd0d850.png

2.反序列化:将网络字节流转换为计算机语言中的内存对象,例如把uint8_t data[6]字节流转化成c语言中的结构体Test。

经过序列化能够使得网络传输获得数据量更少,经过反序列化使得数据接受时格式与原来一致。函数

三:网络编程中的一点小疑惑

(一)前面提到本地字节序和网络字节序(大小端)不一样,那么如何转换??

htonl()--"Host to Network Long"ntohl()--"Network to Host Long"htons()--"Host to Network Short"ntohs()--"Network to Host Short"

以上4种函数实现了对16位、32位数据的网络到本地、本地到网络的转换。布局

补充:数字所占位数小于或等于一个字节(8 bits)时,不要用htons转换。这是由于对于主机来讲,大小端的最小单位为字节(byte)

(二)本地到网络中的哪些数据须要转换??(重点)

不是全部从本地传输到网络中的数据都须要进行大小端的转换!!!

咱们只须要将IP网络层须要访问的数据转化为大端模式,这样网络才知道如何传递、转发数据。而这些数据是指IP地址和端口,IP网络层须要根据这些信息进行转发。ui

IP为网络层,使用的是大端字节序,在IP层中要读取TCP头部中的信息,以肯定要访问的地址。

因此要将port,ip等将在网络层被读取的信息转为大端字节序。

而发送的具体信息,并不被网络层所读取(只是传输),所以只要保证接受方与发送发使用的字节序相同,就不须要进行转换

5e0f81a992843671a4f0b0caff871fa3.png