字节序
字节序,又称端序或尾序,指的是多字节数据在内存中的存放顺序。
大端和小端
计算机有两种储存数据的方式:大端字节序(Big Endian)和小端字节序(Little Endian)。
大端模式:是指数据的高字节保存在内存的低地址中,低字节保存在内存的高地址端。
小端模式:是指数据的高字节保存在内存的高地址中,低字节保存在内存的低地址端。
以一个两字节short型变量0x0102的存储举例:
大端字节序:高位字节在前,低位字节在后,01 | 02,从左往右看着更习惯。 |
小端字节序:低位字节在前,高位字节在后,02 | 01,也存在这种存储顺序。 |
以0x12345678这个数字为例,它的大端模式和小端模式分别如下:
大端字节序符合阅读习惯;小端字节序计算机处理效率高
网络序和主机序
网络字节序:TCP/IP各层协议将字节序定义为Big Endian,即大端模式,TCP/IP协议中使用的字节序是大端序。
主机字节序:整数在内存中存储的顺序,目前以Little Endian,即小端模式,比较普遍(不同的CPU有不同的字节序)。
主机序转换到网络序
htons函数
函数功能:将主机无符号短整形数转换成网络。举例说明如果把htons(16)输出你会看到得到的结果是4096,为什么呢?因为16的十六进制是0X0010,而4096的十六进制是0X1000。
uint16_t htons(uint16_t hostshort)
返回值:返回一个网络字节顺序的值
参数说明:其中hostlong是主机字节顺序表达的16位数,htons中的h表示host意思是主机地址,to表示to意思是去往,转换为的意思,n表示net意思是网络,s表示signed long意思是无符号的短整型。
htonl函数
函数功能:将一个32位数从主机字节顺序转换成网络字节顺序。
uint32_t htonl(uint32_t hostlong)
返回值:返回一个网络字节顺序的值
参数说明:其中hostlong是主机字节顺序表达的32位数,htons中的h表示host意思是主机地址,to表示to意思是去往,转换为的意思,n表示net意思是网络,l 是 unsigned long表示32位长整数
网络序转换到主机序
ntohs函数
函数功能:将一个无符号短整型数从网络字节顺序转换成主机字节顺序。这个函数与htons原理相同,不过是htos是主机序到网络序,而ntohs是网络序到主机序。
uint16_t ntohs(uint16_t netshort)
返回值:返回一个主机字节顺序表达的数
参数说明:其中netshort一个以网络字节顺序表达的16位数,ntohs中的h表示host意思是主机地址,to表示to意思是去往,n表示net意思是网络,s表示signed long意思是无符号的短整型(32位的系统是2字节)。
ntohl函数
函数功能:将一个无符号长整型从网络字节顺序转换成主机字节顺序。这个函数与htonl原理相同,不过是htol是主机序到网络序,而ntohl是网络序到主机序。
uint32_t ntohl函数(uint32_t netlong)
返回值:返回一个主机字节顺序表达的数。
参数说明:其中netlong一个以网络字节顺序表达的32位数,ntohs中的h表示host意思是主机地址,to表示to意思是去往,n表示net意思是网络,s表示signed long意思是无符号的短整型(32位的系统是2字节)。
ip地址转化为用于网络传输的二进制数值
inet_aton函数
头文件:<arpa/inet.h>
函数功能:将一个字符串表示的点分十进制IP地址IP转换为网络字节序存储在addr中
int inet_aton(const char *IP, struct in_addr *addr)
返回值:失败返回0,成功返回1。
参数说明: IP : 输入的点分十进制IP地址 addr : 将IP转换为网络字节序(大端存储)后并保存在addr中
inet_addr函数
in_addr_t inet_addr(const char *cp);
功能:转换网络主机地址(如192.168.1.10)网络字节序二进制值
参数:十进制的ip地址,如
192.168.69.1
返回值:错误时返回-1,成功返回二进制形式的IP地址
将网络传输的二进制数值转化为成点分十进制的ip地址
inet_ntoa函数 头文件:<arpa/inet.h>
函数功能:将一个网络字节序的IP地址(也就是结构体in_addr类型变量)转化为点分十进制的IP地址(字符串)。
char* inet_ntoa(struct in_addr in)
返回值:该函数的返回值是一个字符串,这个字符串是点分十进制的IP地址。
新型网路地址转化函数inet_pton和inet_ntop
p和n分别代表表达(presentation)和数值(numeric)。地址的表达格式通常是ASCII字符串,数值格式则是存放到套接字地址结构的二进制值。
功能上跟inet_aton
和inet_ntoa
类似
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <arpe/inet.h>
/* 将缓冲区中从 CP 开始的互联网号码的演示格式转换为二进制网络格式,
并将结果存储在转换为二进制网络格式,并将结果存储为
接口类型 AF 的结果存储在从 BUF 开始的缓冲区中 */
extern int inet_pton (int __af, const char *__restrict __cp,
void *__restrict __buf) __THROW;
// 将点分十进制ip地址转化为用于网络传输的数值格式
// 成功返回1,若输入不是有效表达式则返回0,错误返回-1
/* 以二进制网络格式转换接口的互联网地址
将从 CP 开始的缓冲区中的 AF 类型转换为表示形式,
并将结果放入长度为 LEN(从 BUF 开始)的缓冲区中。
将结果放入从 BUF 开始长度为 LEN 的缓冲区中. */
extern const char *inet_ntop (int __af, const void *__restrict __cp,
char *__restrict __buf, socklen_t __len)
__THROW;
// 将数值格式转化为点分十进制的ip地址格式
// 成功返回指向结构的指针,错误返回NULL
程序解析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main() {
char IP[] = "192.168.69.1";
struct in_addr address;
int number = inet_aton(IP, &address);
if (number == 0) {
printf("Invalid IP address\n");
return -1;
}
printf("IP address in number format: %u\n", address.s_addr);
printf("IP address in string format: %s\n", inet_ntoa(address));
return 0;
}
运行结果:
1
2
IP address in number format: 21342400
IP address in string format: 192.168.69.1
转换过程:
192.168.69.1
转成二进制为 1100 0000 1010 1000 0100 0101 0000 0001
转成小端序为0000 0001 0100 0101 1010 1000 1100 0000
,十进制为21342400