1. 网络地址结构
Socket通过结构体描述网络地址,最常用的是IPv4地址结构sockaddr_in(定义在<netinet/in.h>):
- struct sockaddr_in {
- sa_family_t sin_family; // 地址族:必须为AF_INET(IPv4)
- in_port_t sin_port; // 端口号(网络字节序)
- struct in_addr sin_addr; // IP地址(网络字节序)
- unsigned char sin_zero[8]; // 填充字段,必须为0(与sockaddr兼容)
- };
- struct in_addr {
- in_addr_t s_addr; // 32位IPv4地址(网络字节序)
- };
- 通用地址结构sockaddr(长度固定,用于函数参数统一):
- struct sockaddr {
- sa_family_t sa_family; // 地址族
- char sa_data[14]; // 地址数据(含端口+IP,长度可变)
- };
使用时需将sockaddr_in*强制转换为sockaddr*传给函数(如bind、connect)。
2. 字节序转换
网络中数据传输必须使用网络字节序(大端字节序),而主机可能是大端或小端(取决于CPU),因此需通过函数转换:
htons():主机字节序 → 网络字节序(16位,用于端口号)。
htonl():主机字节序 → 网络字节序(32位,用于IP地址)。
ntohs():网络字节序 → 主机字节序(16位)。
ntohl():网络字节序 → 主机字节序(32位)。
示例:将端口号8080转换为网络字节序:
uint16_t port = htons(8080); // 关键:端口必须转换,否则可能解析错误
3. IP地址转换
需将“点分十进制字符串”(如"192.168.1.1")与32位整数(网络字节序)互转:
推荐使用兼容IPv4/IPv6的函数:
inet_pton():字符串 → 网络字节序整数(presentation → network)。
inet_ntop():网络字节序整数 → 字符串(network → presentation)。
示例:
- struct sockaddr_in addr;
- // 字符串IP → 网络字节序
- inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
- // 网络字节序 → 字符串
- char ip_str[INET_ADDRSTRLEN]; // INET_ADDRSTRLEN:IPv4字符串最大长度(16)
- inet_ntop(AF_INET, &addr.sin_addr, ip_str, INET_ADDRSTRLEN);
|