sockaddr地址结构——socket

285 阅读2分钟

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或其他,则是由地址族确定的,然后函数内部再强制类型转
     换为所需的地址类型。

image-20220520201004478.png

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));