如何在WINAPI中从addrinfo获取并打印a.b.c.d格式的IP?
问题分析与解决方案
段错误的原因
你的代码存在多个问题导致段错误及功能异常:
- 未初始化Windows Socket环境:在调用
getaddrinfo前必须调用WSAStartup初始化Socket库,否则相关API调用会触发未定义行为。 inet_addr用法完全错误:inet_addr的作用是将点分十进制IP字符串转换为网络字节序的32位整数,而非将sockaddr中的IP转换为字符串。你将inet_addr的返回值(整数)作为printf("%s")的参数,会导致程序把这个整数当作内存地址去读取字符串,直接触发非法内存访问(段错误)。- 未处理
addrinfo链表的释放:getaddrinfo返回的链表需要用freeaddrinfo释放,否则会造成内存泄漏。
正确从addrinfo获取并打印IP的方法
要从addrinfo结构体中提取IPv4地址并以a.b.c.d格式打印,需按以下步骤操作:
- 初始化Windows Socket环境;
- 调用
getaddrinfo获取地址链表; - 遍历链表,将通用
sockaddr结构体转换为IPv4专用的sockaddr_in结构体; - 使用
inet_ntop(推荐,支持IPv6)或inet_ntoa(仅IPv4)将网络字节序的IP转换为字符串; - 释放地址链表并清理Socket环境。
修正后的代码
#include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> // 链接ws2_32.lib #pragma comment(lib, "ws2_32.lib") int main(int argc, char ** argv) { if (argc < 3) { printf("参数不足:需要传入服务器地址和端口\n"); return -1; } WSADATA wsData; int result = WSAStartup(MAKEWORD(2, 2), &wsData); if (result != 0) { printf("WSAStartup失败,错误码:%d\n", result); return -1; } struct addrinfo hints, *ptr = NULL; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; result = getaddrinfo(argv[1], argv[2], &hints, &ptr); if (result != 0) { printf("getaddrinfo失败,错误码:%d\n", result); WSACleanup(); return -1; } // 遍历addrinfo链表,打印每个IPv4地址 struct addrinfo *current = ptr; while (current != NULL) { if (current->ai_family == AF_INET) { struct sockaddr_in *sockaddr_ipv4 = (struct sockaddr_in *)current->ai_addr; char ip_str[INET_ADDRSTRLEN]; // 使用inet_ntop转换为点分十进制字符串 inet_ntop(AF_INET, &sockaddr_ipv4->sin_addr, ip_str, INET_ADDRSTRLEN); printf("服务器IP:%s\n", ip_str); } current = current->ai_next; } // 释放addrinfo链表 freeaddrinfo(ptr); // 清理Socket环境 WSACleanup(); return 0; }
关键代码解释
WSAStartup与WSACleanup:前者初始化Windows Socket库,后者在程序结束前清理资源,是WinAPI Socket编程的必要步骤。sockaddr转sockaddr_in:因为我们指定了AF_INET(IPv4),所以可以安全地将通用的sockaddr结构体转换为IPv4专用的sockaddr_in,其中sin_addr字段存储了网络字节序的IP地址。inet_ntop:相比inet_ntoa,inet_ntop支持IPv6,且使用用户提供的缓冲区,避免了inet_ntoa的线程安全问题(inet_ntoa返回的是静态缓冲区)。
内容的提问来源于stack exchange,提问作者loaded_dypper
相关产品推荐
相关产品推荐

