You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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格式打印,需按以下步骤操作:

  1. 初始化Windows Socket环境;
  2. 调用getaddrinfo获取地址链表;
  3. 遍历链表,将通用sockaddr结构体转换为IPv4专用的sockaddr_in结构体;
  4. 使用inet_ntop(推荐,支持IPv6)或inet_ntoa(仅IPv4)将网络字节序的IP转换为字符串;
  5. 释放地址链表并清理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:45:37