服务器测评网
我们一直在努力

Linux C获取IP地址有哪些常用方法?

在Linux环境下使用C语言获取IP地址是网络编程中的常见需求,通常涉及系统调用和套接字编程,以下是几种主流的实现方式,涵盖本地IP和远程IP的获取方法,并提供关键代码示例和注意事项。

Linux C获取IP地址有哪些常用方法?

获取本地主机IP地址

获取本地主机IP地址通常需要结合gethostname()gethostbyname()函数,或使用更现代的getaddrinfo()接口,前者在IPv4环境下较为简单,后者则支持IPv4和IPv6双栈。

使用gethostname()gethostbyname()

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
int main() {
    char hostname[1024];
    struct hostent *host;
    if (gethostname(hostname, sizeof(hostname)) == -1) {
        perror("gethostname");
        exit(EXIT_FAILURE);
    }
    host = gethostbyname(hostname);
    if (host == NULL) {
        herror("gethostbyname");
        exit(EXIT_FAILURE);
    }
    printf("Local IP addresses:\n");
    for (int i = 0; host->h_addr_list[i] != NULL; i++) {
        struct in_addr addr;
        memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
        printf("%s\n", inet_ntoa(addr));
    }
    return 0;
}

注意事项gethostbyname()已被标记为过时(deprecated),且不支持IPv6,实际开发中建议优先使用getaddrinfo()

Linux C获取IP地址有哪些常用方法?

使用getaddrinfo()(推荐)

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
int main() {
    struct addrinfo hints, *res, *p;
    char ipstr[INET6_ADDRSTRLEN];
    int status;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; // AF_INET或AF_INET6强制指定版本
    hints.ai_socktype = SOCK_STREAM;
    if ((status = getaddrinfo("localhost", NULL, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 1;
    }
    printf("Local IP addresses:\n");
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        const char *ipver;
        if (p->ai_family == AF_INET) { // IPv4
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else { // IPv6
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        printf("%s: %s\n", ipver, ipstr);
    }
    freeaddrinfo(res);
    return 0;
}

获取远程主机IP地址

获取远程主机IP地址通常通过域名解析实现,getaddrinfo()是最佳选择,它能够处理IPv4/IPv6并自动解析DNS。

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <hostname>\n", argv[0]);
        return 1;
    }
    struct addrinfo hints, *res, *p;
    char ipstr[INET6_ADDRSTRLEN];
    int status;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 1;
    }
    printf("IP addresses for %s:\n", argv[1]);
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        const char *ipver;
        if (p->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        }
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        printf("%s: %s\n", ipver, ipstr);
    }
    freeaddrinfo(res);
    return 0;
}

通过套接字获取网络接口IP

若需获取特定网络接口(如eth0)的IP地址,可以使用ioctl()结合struct ifreq,但此方法需要管理员权限且仅适用于IPv4。

Linux C获取IP地址有哪些常用方法?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <sys/ioctl.h>
int main() {
    int sockfd;
    struct ifreq ifr;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    strncpy(ifr.ifr_name, "eth0", IFNAMSIZ - 1);
    if (ioctl(sockfd, SIOCGIFADDR, &ifr) == -1) {
        perror("ioctl");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
    printf("Interface eth0 IP: %s\n", inet_ntoa(addr->sin_addr));
    close(sockfd);
    return 0;
}

编译与运行注意事项

  1. 编译选项:使用gcc -o program program.c编译,若涉及<linux/if.h>等头文件,可能需要链接-lm-lnsl库。
  2. 权限问题ioctl()方法需要root权限,而getaddrinfo()无需特殊权限。
  3. 错误处理:实际开发中需全面检查函数返回值,避免内存泄漏(如freeaddrinfo()的调用)。

通过以上方法,开发者可根据实际需求选择合适的IP获取策略,现代Linux网络编程推荐优先使用getaddrinfo(),其兼容性和功能性更优,同时注意处理IPv4/IPv6双栈场景。

赞(0)
未经允许不得转载:好主机测评网 » Linux C获取IP地址有哪些常用方法?