📜  我的 ip - C 编程语言(1)

📅  最后修改于: 2023-12-03 15:09:58.191000             🧑  作者: Mango

我的 IP - C 编程语言

在现代互联网时代,IP 地址已经成为计算机网络中不可或缺的部分。在这里,我们将介绍如何用 C 编程语言获取当前计算机的 IP 地址。

获取 IP 地址的函数

C 语言中,可以使用 getaddrinfo 函数来获取 IP 地址。该函数可以支持 IPv4 和 IPv6 地址类型,并且可以选择返回所需协议类型的地址信息。下面是一个使用 getaddrinfo 函数获取 IP 地址的简单例子:

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    struct addrinfo hints, *res, *p;
    int status;
    char ipstr[INET6_ADDRSTRLEN];

    if (argc < 2) {
        fprintf(stderr, "usage: %s hostname\n", argv[0]);
        return 1;
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;    // AF_INET or AF_INET6 to force version
    hints.ai_socktype = SOCK_STREAM;

    if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 2;
    }

    printf("IP addresses for %s:\n\n", argv[1]);

    for (p = res; p != NULL; p = p->ai_next) {
        // convert address to IPv4 or IPv6 string
        void *addr;
        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";
        }

        // convert the IP to a string and print it:
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
        printf("  %s: %s\n", ipver, ipstr);
    }

    freeaddrinfo(res); // free the linked list

    return 0;
}

在该例子中,我们首先定义了一个 addrinfo 的结构体变量 hints,并赋值了需要获取的地址类型为 AF_UNSPEC,即既可以获取 IPv4 地址,也可以获取 IPv6 地址。然后使用 getaddrinfo 函数来获取目标主机名对应的地址信息,并将结果存放在 res 指针所指的 addrinfo 结构体链表中。最后使用 inet_ntop 函数将 struct sockaddr 结构体类型的 IP 地址转化为字符串,便于输出。

代码片段

下面是示例代码片段,用于获取本地主机的 IP 地址:

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

void getmyip(char *ipstr, int len)
{
    char hostname[256];
    struct addrinfo hints, *res, *p;
    int status;

    // get hostname
    if (gethostname(hostname, sizeof(hostname)) < 0) {
        perror("gethostname");
        return;
    }

    // get address info
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return;
    }

    // loop through all the results and get the IP address
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        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";
        }

        // convert the IP to a string and copy it to the result buffer
        inet_ntop(p->ai_family, addr, ipstr, len);
        break; // only need first IP address
    }

    freeaddrinfo(res);
}

使用该代码片段,可以调用 getmyip 函数来获取本地主机的 IP 地址,并将结果存储在 ipstr 变量中。如果调用成功,函数将返回 0,否则将返回 -1。下面是一个使用该函数的例子:

#include <stdio.h>

int main()
{
    char ipstr[INET6_ADDRSTRLEN];
    if (getmyip(ipstr, sizeof(ipstr)) == 0) {
        printf("My IP address is: %s\n", ipstr);
    } else {
        fprintf(stderr, "Error: unable to get IP address.\n");
        return 1;
    }
    return 0;
}

在该例子中,我们调用 getmyip 函数来获取本地主机的 IP 地址,并将结果输出到标准输出流中。如果获取成功,将输出类似于 My IP address is: 192.168.1.100 的信息,否则将输出错误信息并退出程序。