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

求助:使用C语言getaddrinfo获取google.com的IP地址失败

Hey there, I get it—trying to fetch a domain's IP address can feel frustrating when most tutorials fixate on local socket pairs (which are for inter-process communication on the same machine, by the way) and even trusted resources don't work out of the box for you. Let's break down what's wrong with your code and fix it step by step.

What's Going Wrong in Your Code

There are three key issues causing the garbage output and segmentation fault:

  1. No error checking for getaddrinfo
    This function returns a non-zero error code if it fails (e.g., DNS resolution fails, invalid parameters). If you skip checking this, you might end up operating on a NULL res pointer, which leads to crashes.

  2. Broken loop traversal
    Your for loop initializes i = res but then uses res = res->ai_next to advance the pointer, while the loop condition checks i != 0. This means you're not actually using i to traverse the list, and eventually res becomes NULL—accessing res->ai_addr at that point triggers a segmentation fault.

  3. Directly printing sa_data is incorrect
    The sa_data field in struct sockaddr stores binary address data, not human-readable strings. You need to convert this binary data to a readable IP format using functions like inet_ntop, and first cast the generic sockaddr to the correct IPv4 or IPv6 struct based on the address family.

Fixed Code with Explanations

Here's a corrected version that properly resolves google.com and prints its IP addresses:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>

int main(void) {
    struct addrinfo hints, *res, *current_addr;
    int status;
    char ip_buffer[INET6_ADDRSTRLEN]; // Buffer big enough for IPv6 addresses

    // Initialize hints to specify what kind of addresses we want
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;     // Accept both IPv4 and IPv6
    hints.ai_socktype = SOCK_STREAM; // We're looking for TCP addresses (matches port 443)

    // Call getaddrinfo and check for errors
    if ((status = getaddrinfo("google.com", "443", &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(status));
        return 1;
    }

    printf("IP addresses for google.com:\n\n");

    // Traverse the linked list of addresses
    for (current_addr = res; current_addr != NULL; current_addr = current_addr->ai_next) {
        void *raw_ip;
        const char *ip_version;

        // Cast to the correct struct based on address family
        if (current_addr->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)current_addr->ai_addr;
            raw_ip = &(ipv4->sin_addr);
            ip_version = "IPv4";
        } else {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)current_addr->ai_addr;
            raw_ip = &(ipv6->sin6_addr);
            ip_version = "IPv6";
        }

        // Convert binary IP to human-readable string
        inet_ntop(current_addr->ai_family, raw_ip, ip_buffer, sizeof(ip_buffer));
        printf("  %s: %s\n", ip_version, ip_buffer);
    }

    // Free the memory allocated by getaddrinfo (critical to avoid leaks!)
    freeaddrinfo(res);

    return 0;
}

Key Improvements:

  • hints struct: Tells getaddrinfo exactly what type of addresses we need (TCP, IPv4/IPv6) instead of letting it return arbitrary address types.
  • Error handling: Checks if getaddrinfo fails and prints a meaningful error message using gai_strerror.
  • Proper list traversal: Uses current_addr to iterate through the linked list without modifying the original res pointer, preventing null pointer access.
  • IP conversion: Uses inet_ntop to convert binary address data to a readable string, with logic to handle both IPv4 and IPv6.
  • Memory cleanup: Calls freeaddrinfo to release the memory allocated by getaddrinfo—always remember this to avoid memory leaks!

Quick Note on Local Sockets

You mentioned confusion about tutorials focusing on local client/server sockets: those use the AF_UNIX (or AF_LOCAL) address family, and they're for communication between processes on the same machine (e.g., a local database and a desktop app, or system services talking to each other). They don't involve network communication or DNS resolution, which is why they don't help with your goal of fetching google.com's IP.

内容的提问来源于stack exchange,提问作者RaspberMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:23:13