sockaddr地址结构
bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
// 像bind这些函数API在很早的时候就有了
// 而struct sockaddr_in 是后面出现的, 针对IPV4
// IPv4即4个字节(32位)来表示IP,那么也就4亿多IP
// 所以后面出现了IPv6, 用128个位来表示IP地址
一、sockaddr数据结构
struct sockaddr: 很多网络编程函数诞生早于IPV4,那时候都使用的是sockaddr结构体,为了向前兼容,现在sockaddr退化成了
(void*)的作用,传递一个地址给函数,至于这个函数是sockaddr_in或其他,则是由地址族确定的,然后函数内部再强制类型转
换为所需的地址类型。
1. struct sockaddr与struct sockaddr_in
struct sockaddr {
sa_family_t sa_family; //选择地址家族,AF_xxx | 例如是IPV4的就是选择AF_INET | AF_INET6
char sa_data[14]; // 地址数据
}
struct sockaddr_in {
sa_family_t sin_family; // 地址家族: AF_INET
in_port_t sin_port; // 两字节的端口号(网络字节顺序)
struct in_addr sin_addr; // 因特网地址
}
// 因特网地址
struct in_addr {
uint32_t s_addr; //32位的网络字节顺序的IP地址(32位的无符号整型数)
// 而且这个整型数要转换成字符串
// 再如,若客户端要去连接某个IP地址,要将字符串转换成整型数
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET; // 选择协议家族IPV4
// INADDR_ANY 宏定义 代表本地所有IP地址 0.0.0.0 整型数
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //因为这是网络字节顺序的IP地址,所以要用htonl转换一下
server_addr.sin_port = htons(SERVER_PORT); // 网络字节顺序
// 在调用bind的时候,因为bind要求传递的参数是struct sockaddr 结构体,所以要做强制转换
// 实际上struct sockaddr和struct sockaddr_in结构相似,都是16个字节
/* 在这里指定的是IPv4 ,所以bind会在绑定的时候根据地址家族AF_INET(IPV4的),会自动的把传递的&server_addr再强制转换
成sockaddr_in,所以不会有问题,即使二者结构不一样(在内部还是用的sockaddr_in处理)
*/
bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));