- (一)通用socket地址
- (1)struct sockaddr
- (2)struct sockaddr_storage
- (二)专用socket地址
- (1) UNIX本地域协议族的socket地址结构体
- (2)TCP/IP协议族地址结构体
- (三)IP地址转换函数
- (1)将一个点分十进制字符串IP地址转成长整型
- (2)将一个字符串IP地址转换为一个32位的网络序列IP地址
- (3)将网络序列IP地址转成点分十进制字符串IP地址
- (4)IP地址转换函数测试代码
- (四)端口转换函数
- (1)主机端口转成网络端口(短整型short 16位)
- (2)主机端口转成网络端口(长整型int 32位)
- (3)网络端口转成主机端口(短整型short 16位)
- (4)网络端口转成主机端口(长整型int 32位)
- (5)端口转换测试代码
- struct socketaddr类型是网络编程的通用地址类型,其定义如下
头文件:bits/socket.h
#includestruct sockaddr { sa_family_t sa_family; //地址族(协议族)类型的变量 char sa_data[14]; //存放socket地址值 };
- 协议族和地址族的关系
注意:宏PF_*和AF_*都定义在bits/socket.h中,两者的值相同,二者通常混用
- 协议族及其地址值
sa_data无法容纳大部分协议的地址值,所以产生了(2)
头文件:bits/socket.h
#includestruct sockaddr_storage { sa_family_t sa_family; unsigned long int __ssalign; char __ss_padding[128 - sizeof(__ssalign)]; };
该结构体空间够大,可存放地址值,而且使用__ss_align进行了字节对齐,但都不是很好用!!
由于(1)(2)设置IP地址和端口号都要执行位操作,比较繁琐,所以linux对各个协议提供了专用地址
(二)专用socket地址 (1) UNIX本地域协议族的socket地址结构体
头文件:sys/un.h
#include(2)TCP/IP协议族地址结构体struct sockaddr_un { sa_family_t sin_family; //地址族:AF_UNIX char sun_path[108]; //文件路径名 };
头文件:netinet/in.h
- IPv4
#includestruct sockaddr_in { sa_family_t sin_family; //地址族:AF_INET u_int16_t sin_port; //端口号,网络字节序 struct in_addr sin_adrr;//IPv4地址结构体 };
#includestruct in_addr { u_int32_t s_addr; //IPv4地址,网络字节序 };
- IPv6
#includestruct sockadrr_in6 { sa_family_t sin6_family; //地址族:AF_INET u_int16_t sin6_port; //端口号:网络字节序 u_int32_t sin6_flowinfo; //流信息:设置0 struct in6_addr sin6_addr; //IPv6地址体 u_int32_t sin6_scope_id; //scope ID,处于试验阶段 };
#includestruct in6_addr { unsigned char sa_addr[16]; //IPv6地址:网络字节序 };
注意:在使用socket编程接口时,对这两个专用的地址结构体需要强制转换成struct sockaddr类型
(三)IP地址转换函数
一般使用字符串表示IP地址:点分十进制表示IPv4地址,十六进制字符串表示IPv6地址。
编程使用中需要将字符串转成整型数据才能使用;
头文件:arpa/inet.h
(1)将一个点分十进制字符串IP地址转成长整型in_addr_t inet_addr(const char* strptr);
- strptr :点分十进制的字符串IP地址
- 返回值:成功无符号长整型数。失败返回INADDR_NONE
int inet_aton(const char* cp, struct in_addr* inp);
- cp : 字符串IP地址
- inp : 用来存放转换后的网络序列
- 返回值:成功返回1,IP地址不正确导致失败返回0,不设置errno值
char* inet_ntoa(struct in_addr in);
- in : 网络序列IP地址
- 返回值:成功返回点分十进制的字符串IP地址,失败返回NULL
- 代码:
#include #includeint main() { //将字符串IP地址转成无符号长整形 in_addr_t ret = inet_addr("127.0.0.1"); printf("ret = %dn", ret); //将一个字符串IP地址转成32位网络序列IP地址 struct in_addr buff; if(inet_aton("127.0.0.1", &buff) != 0) { printf("buff.s_addr = %dn", buff.s_addr); } //将网络字节序列转成点分十进制字符串IP地址 char* s = inet_ntoa(buff); if(s != NULL) { printf("s = %sn", s); } return 0; }
-
结果:
-
拓展:
头文件:arpa/inet.h
(1)主机端口转成网络端口(短整型short 16位)uint16_t htons(uint16_t hostshort);
(2)主机端口转成网络端口(长整型int 32位)uint32_t htons(uint32_t hostlong);
(3)网络端口转成主机端口(短整型short 16位)uint16_t htons(uint16_t netshort);
(4)网络端口转成主机端口(长整型int 32位)uint16_t htons(uint32_t netlong);
(5)端口转换测试代码- 代码:
#include #includeint main() { //将主机端口6000转为网络端口 uint16_t port_net = htons(6000); printf("网络端口port_net = %dn", port_net); //将上一步的网络端口在转成主机端口 uint16_t port_short = ntohs(port_net); printf("主机端口port_short = %dn", port_short); return 0; }
- 结果:



