网络地址
通常分为 IPv4 和 IPv6 IPv4地址分为网络地址和主机地址 传输数据时,先根据网络地址找到对应网络,然后在网络内找到对应主机。
表示 IPv4 的结构体
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family; //地址族
in_port_t sin_port; //16位端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用
};
其中的struct in_addr
如下:
/*
* Internet address (a structure for historical reasons)
*/
struct in_addr {
in_addr_t s_addr;
};
网络字节序与地址变换
不同 CPU 保存数值的方式不同,同样是 4 字节的整型 1,表示方式可以有以下两种方式: 00000000 00000000 00000000 00000001 00000001 00000000 00000000 00000000
字节序与网络字节序
- 大端序:高位字节存放到低位地址
- 小端序:高位字节存放到高位地址 比如在0x20号地址开始保存数据0x12345678 0x12是高位字节,0x78是低位字节
不同端序的计算机互相收发信息会有问题,因此需要统一收发顺序 ::默认在网络中统一为大端序
字节序转换函数
// 前两个通常用于端口号转换,后两个用于 IP 地址转换
unsigned shorted htons(unsigned short);
unsigned shorted ntohs(unsigned short);
unsigned long ntohl(unsigned long);
unsigned long htonl(unsigned long);
h代表主机字节序,n 代表网络字节序,s 代表 short,l 代表 long
主机字节序转换为网络字节序
/**
字节序转换
*/
unsigned short host_prot = 0x1234;
unsigned short net_port;
unsigned long host_addr = 0x12345678;
unsigned long net_addr;
net_port = htons(host_prot);
net_addr = htonl(host_addr);
printf("net_port = %#x\n", net_port); //0x3412
printf("net_addr = %#lx\n", net_addr); //0x78563412
Intel 和 AMD 用的都是小端序标准,因此这里能看到变化。
网络地址的初始化和分配
将字符串信息转换为网络字节序
struct sockaddr_in {
__uint8_t sin_len;
sa_family_t sin_family; //地址族
in_port_t sin_port; //16位端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用
};
可以看到,这里保存 IP 地址信息的是32 位整数型,因此需要进行转换
/**
字符串转换为网络字节序
*/
char *addr1 = "1.2.3.4";
char *addr2 = "1.2.3.256";
//inet_addr:成功时返回 32 位大端序整型数值
unsigned long res = inet_addr(addr1);
if (res == INADDR_NONE) {
printf("invalid res");
} else {
printf("res = %#lx\n", res);
}
unsigned long res1 = inet_addr(addr2);
if (res1 == INADDR_NONE) {
printf("invalid res1\n");
} else {
printf("res1 = %#lx\n", res1);
}
return 0;
int inet_aton(const char *, struct in_addr * addr)
addr:保存转换结果的in_addr结构体变量的地址值
char *addr3 = "2.3.4.5";
struct sockaddr_in addr_inet;
if (!inet_aton(addr3, &addr_inet.sin_addr)) {
printf("erro...");
} else {
printf("res = %#x", addr_inet.sin_addr.s_addr);
}