在网络编程中,sockaddr
结构体用于表示套接字的地址信息。由于不同协议(如 IPv4、IPv6、Unix 域套接字)的地址格式不同,实际使用中通常通过以下三种变体结构来处理不同类型的地址:
1. 通用地址结构:struct sockaddr
-
用于类型兼容性,所有具体地址结构需强制转换为此类型传递给套接字函数。
-
字段 :
cstruct sockaddr { sa_family_t sa_family; // 地址族(如 AF_INET, AF_INET6, AF_UNIX) char sa_data[14]; // 协议特定地址信息(实际不直接使用) };
2. IPv4 地址结构:struct sockaddr_in
-
用于 IPv4 协议的地址表示。
-
字段 :
cstruct sockaddr_in { sa_family_t sin_family; // 地址族(必须设为 AF_INET) in_port_t sin_port; // 16 位端口号(需用 `htons()` 转换字节序) struct in_addr sin_addr; // 32 位 IPv4 地址 char sin_zero[8]; // 填充字段(通常置零) }; struct in_addr { in_addr_t s_addr; // IPv4 地址(32 位整数,需用 `inet_pton()` 或 `htonl()` 转换) };
-
示例 :
cstruct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(8080); inet_pton(AF_INET, "192.168.1.1", &addr.sin_addr); memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
3. IPv6 地址结构:struct sockaddr_in6
-
用于 IPv6 协议的地址表示。
-
字段 :
cstruct sockaddr_in6 { sa_family_t sin6_family; // 地址族(必须设为 AF_INET6) in_port_t sin6_port; // 16 位端口号(需用 `htons()` 转换) uint32_t sin6_flowinfo; // IPv6 流信息(通常为 0) struct in6_addr sin6_addr; // 128 位 IPv6 地址 uint32_t sin6_scope_id; // 接口范围 ID(用于链路本地地址) }; struct in6_addr { unsigned char s6_addr[16]; // IPv6 地址(128 位) };
-
示例 :
cstruct sockaddr_in6 addr6; addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(8080); inet_pton(AF_INET6, "2001:db8::1", &addr6.sin6_addr);
4. Unix 域套接字结构:struct sockaddr_un
-
用于本地进程间通信(Unix Domain Socket)。
-
字段 :
cstruct sockaddr_un { sa_family_t sun_family; // 地址族(必须设为 AF_UNIX 或 AF_LOCAL) char sun_path[108]; // 文件系统路径名(需唯一且存在) };
-
示例 :
cstruct sockaddr_un unix_addr; unix_addr.sun_family = AF_UNIX; strncpy(unix_addr.sun_path, "/tmp/mysocket", sizeof(unix_addr.sun_path) - 1);
关键注意事项
-
类型转换 :具体结构(如
sockaddr_in
)在使用时需强制转换为struct sockaddr*
。cbind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
-
字节序转换 :IPv4/IPv6 的端口号和地址需用
htons()
、htonl()
或inet_pton()
转换网络字节序。 -
长度参数 :传递地址结构时需指定实际长度(如
sizeof(struct sockaddr_in)
)。
通过这三种结构体,可以灵活处理不同协议族的网络地址,是网络编程中地址管理的核心基础。