如何用getaddrinfo编程获取主机IPv4地址?程序输出空行求助
问题分析与解决方案
问题根源
核心错误在于直接访问sockaddr结构体的sa_data字段:
struct sockaddr是通用地址结构体,sa_data存储的是与地址族相关的原始二进制数据,并非可读的IP字符串。对于IPv4来说,该字段包含端口和IP的二进制形式,无法通过puts直接输出为可读内容,因此显示空行。- 循环结束后判断
rp == NULL就报错的逻辑有误——遍历完所有地址节点后rp自然会变为NULL,这是正常的遍历结束状态,不是失败。
修正后的代码
要正确获取并打印IPv4地址,需将通用sockaddr转换为IPv4专用的struct sockaddr_in,再通过inet_ntop函数将二进制IP转换为可读字符串,同时记得释放getaddrinfo返回的内存:
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> // 新增头文件,用于inet_ntop int main() { struct addrinfo hints; struct addrinfo *result, *rp; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* IPv4 */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; /* Any protocol */ int res = getaddrinfo("google.com", NULL, &hints, &result); if (res != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(res)); exit(EXIT_FAILURE); } /* 遍历所有返回的地址节点 */ for (rp = result; rp != NULL; rp = rp->ai_next) { // 将通用sockaddr转换为IPv4专用的sockaddr_in struct sockaddr_in *ipv4_addr = (struct sockaddr_in *)rp->ai_addr; // 用inet_ntop将二进制IP转换为字符串 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ipv4_addr->sin_addr, ip_str, INET_ADDRSTRLEN); printf("IPv4地址: %s\n", ip_str); } // 释放getaddrinfo返回的链表内存,避免泄漏 freeaddrinfo(result); return 0; }
关键修正点说明
- 新增
<arpa/inet.h>头文件:提供inet_ntop函数声明,用于将二进制网络地址转换为可读字符串。 - 类型转换:因已指定
ai_family = AF_INET,可安全将rp->ai_addr(struct sockaddr*)强制转换为struct sockaddr_in*,获取IPv4专用地址结构。 - 地址转换与打印:通过
inet_ntop从sin_addr字段提取二进制IP,转换为字符串后输出。 - 内存释放:调用
freeaddrinfo(result)释放getaddrinfo动态分配的链表内存,避免内存泄漏。 - 移除错误判断:删除循环后
if (rp == NULL)的报错逻辑,该状态是遍历完成的正常结果。
内容的提问来源于stack exchange,提问作者user4035
相关产品推荐
相关产品推荐

