ubuntu 如何从C++代码中获取vm的IPv6地址?

huwehgph  于 2023-03-22  发布在  其他
关注(0)|答案(1)|浏览(142)

我有一个虚拟机,我想从C++代码中获取IPv6地址。我已经找到getaddrinfo函数,但我不明白使用什么参数来获取IPv6地址。我已经尝试过

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

using namespace std;

int main() {
    addrinfo hint, *res = NULL, *p = NULL;
    int err;
    memset(&hint, 0, sizeof hint);
    hint.ai_family = AF_UNSPEC;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_flags = AI_ADDRCONFIG;
    err = getaddrinfo(NULL, "http", &hint, &res);

    std::cout << res->ai_canonname;

    return 0;
}

但是得到Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)错误。如何从C++代码中获取vm的IPv6地址?

zaq34kh6

zaq34kh61#

在使用getaddrinfo()的结果之前,您不会检查getaddrinfo()是否成功。
另外,res->ai_canonname不包含您要查找的IP地址。它存储在res->ai_addr中。但是,它以二进制形式存储(作为sockaddr_in6结构体)。要获得文本形式,您可以将二进制IP传递给getnameinfo()inet_ntop()或其他等效函数。
另外,getaddrinfo()返回IP的链接列表。一台机器可以安装多个IP,因此您应该遍历整个列表,打印出每个可用的IP。
试试类似这样的方法:

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

using namespace std;

int main() {
    addrinfo hint = {}, *res;

    hint.ai_family = AF_INET6;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_flags = AI_ADDRCONFIG;

    int err = getaddrinfo(NULL, "http", &hint, &res);
    if (err != 0) {
        std::cerr << "getaddrinfo failed, error " << err << '\n';
    }
    else {
        char ip[NI_MAXHOST];

        for (addrinfo *p = res; p != NULL; p = p->ai_next) {

            if (getnameinfo(p->ai_addr, p->ai_addrlen, ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0)
                continue;

            /* alternatively:
            if (inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(p->ai_addr)->sin6_addr), ip, NI_MAXHOST) == NULL)
                continue;
            */

            std::cout << ip << '\n';
        }

        freeaddrinfo(res);
    }

    return 0;
}

然而,话虽如此,getaddrinfo()并不是检索本地IP的最佳选择。如果您的平台支持它,您应该使用getifaddrs()或等效产品,例如:

#include <iostream>
#include <sys/types.h>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <netdb.h>
//#include <arpa/inet.h>

using namespace std;

int main() {

    ifaddrs *res = NULL;

    int err = getifaddrs(&res);
    if (err < 0) {
        std::cerr << "getifaddrs failed, error " << err << '\n';
    }
    else {
        char ip[NI_MAXHOST];

        for (ifaddrs *p = res; p != NULL; p = p->ifa_next) {
            if ((p->ifa_addr == NULL) || (p->ifa_addr->sa_family != AF_INET6))
                continue;

            if (getnameinfo(p->ifa_addr, sizeof(sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0)
                continue;

            /* alternatively:
            if (inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(res->ifa_addr)->sin6_addr), ip, NI_MAXHOST) == NULL)
                continue;
            */

            std::cout << ip << '\n';
        }

        freeifaddrs(addrs);
    }

    return 0;
}

相关问题