网络字节序和主机字节序

Posted xingguang1130

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络字节序和主机字节序相关的知识,希望对你有一定的参考价值。

1、大端、小端字节序

考虑一个16位整数,它由2个字节组成。内存中存储这两个字节有两种方法:一种是将低序字节存储在起始地址,这称为小端(little-endian)字节序;另一种方法是将高序字节存储在起始地址,这称为大端(big-endian)字节序。如下所示:

技术图片

 

 

 

 术语“大端”和“小端”表示多个字节值的哪一端(小端或大端)存储在该值的起始地址。

遗憾的是,这两种字节序之间没有标准可循,两种格式都有系统使用。比如,Inter x86、ARM核采用的是小端模式,Power PC、MIPS UNIX和HP-PA UNIX采用大端模式。

 

2、网络字节序和主机字节序

网络字节序

  网络字节序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节序采用big endian排序方式。

主机字节序

  不同的机器主机字节序不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。我们把某个给定系统所用的字节序称为主机字节序(host byte order)。比如x86系列CPU都是little-endian的字节序。

  由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序。

 

网络字节序与主机字节序之间的转换函数:htons(), ntohs(), htons(),htonl(),位于头文件<netinet/in.h>,htons和ntohs完成16位无符号数的相互转换,htonl和ntohl完成32位无符号数的相互转换。

在使用little endian的系统中,这些函数会把字节序进行转换;

在使用big endian类型的系统中,这些函数会定义成空宏;

在网络程序开发时 或是跨平台开发时,也应该注意保证只用一种字节序,不然两方的解释不一样就会产生bug。

 

3、IP地址的三种表示格式及在开发中的应用

 

 

1)点分十进制表示格式

2)网络字节序格式

3)主机字节序格式

用IP地址127.0.0.1为例:

  第一步   127     .         0         .         0         .        1                 把IP地址每一部分转换为8位的二进制数。

  第二步 01111111     00000000     00000000     00000001      =   2130706433   (主机字节序)

  然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:

  第三步 00000001     00000000     00000000    01111111        =   16777343        (网络字节序)

eg:

  struct sockaddr_in addrSrv;

//  addrSrv.sin_addr.S_un.S_addr=htonl(2130706433);  
  addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
  addrSrv.sin_family=AF_INET;
  addrSrv.sin_port=htons(6000);

 

4、inet_aton()、inet_addr()和inet_aton()函数

头文件: <arpa/inet.h>

1)int inet_aton(const char *strptr, struct in_addr *addrptr);

将strptr所指C字符串转换成一个32位的网络字节序二进制值,并通过指针addrptr来存储。若成功则返回1,否则返回0。

2)in_addr_t inet_addr(const char *strptr)

若字符串有效,则返回值为32位的网络字节序二进制值,否则为INADDR_NONE。

该函数存在一个问题,所有2^32个可能的二进制值都是有效的IP地址(0.0.0.0---255.255.255.255),但是当出错时该函数返回INADDR_NONE常值(通常是一个32位均为1的值)。这意味着点分十进制数串255.255.255.255不能由该函数处理,因为它的二进制值用来指示该函数失败。所以该函数已经被废弃,应该尽量用inet_aton()函数,或者将要说到的inet_pton()函数。

3)char *inet_ntoa(struct in_addr inaddr);

将一个32位的网络字节序二进制值IPv4地址转换成相应的点分十进制数串。该函数以一个结构而不是以指向该结构的一个指针作为其参数。

返回:指向一个点分十进制数串的指针

 

 

5、inet_pton()和inet_ntop()函数

这两个函数是随着IPv6出现的新函数,对于IPv4地址和IPv6地址都适用。函数名中p和n分别代表表达(presentation)和数值(numeric)。

头文件: <arpa/inet.h>

技术图片

 

 技术图片

 

 技术图片

 

 技术图片技术图片

 

 技术图片

 

 技术图片

 

 技术图片

 

 技术图片

 

 技术图片

 

 总结这几个转换函数:

技术图片

 

以上是关于网络字节序和主机字节序的主要内容,如果未能解决你的问题,请参考以下文章

主机字节序和网络字节序

网络字节序和主机字节序

主机字节序和网络字节序

主机序和网络序以及使用例子

python通过ntohl和htonl等函数实现主机字节序和网络字节序相互转换

Python网络编程——主机字节序和网络字节序之间的相互转换