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(),位于头文件,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;
4、inet_aton()、inet_addr()和inet_aton()函数
头文件:
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)。
头文件:
总结这几个转换函数: