在c中获取本地IP地址

新手上路,请多包涵

我有一个获取本地 IP 地址的代码。这是我使用的代码。

 typedef std::map<string,string> settings_t;

void loadLocalIp (settings_t &ipConfig)
{
    struct ifaddrs * ifAddrStruct=NULL;
    struct ifaddrs * ifa=NULL;
    void * tmpAddrPtr=NULL;

    getifaddrs(&ifAddrStruct);

    for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
            // is a valid IP4 Address
            tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
            char addressBuffer[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);

            string key(ifa->ifa_name);
            string value(addressBuffer);
            cout<<key<<" =1 " <<value<<endl;
            ipConfig.insert(std::pair<string,string>(key, value));

           // printf("'%s': %s\n", ifa->ifa_name, addressBuffer);
         }
     }
    if (ifAddrStruct!=NULL)
        freeifaddrs(ifAddrStruct);//remember to free ifAddrStruct
}

int main()
{
    settings_t ipConfig;
    loadLocalIp(ipConfig);
    cout<<ipConfig.at("enp2s0")<<endl;
    return 0;
}

所以我的结果是

lo =1 127.0.0.1
enp2s0 =1 172.20.55.6
172.20.55.6

但在另一台计算机上,接口名称不同。他们得到如下结果,

 lo =1 127.0.0.1
ens32 =1 172.20.55.9
terminate called after throwing an instance of 'std::out_of_range'
  what():  map::at
Aborted (core dumped)

无论接口名称是什么,我都想获得我的 IP 地址。如果接口名称因不同计算机而异,如何获取我的本地 IP 地址。无论接口名称是什么,它都应该给出 IP 地址。我怎样才能做到这一点?

我的问题是,现在我正在通过这种方法获取本地 IP。但无论接口名称是什么,我都应该获得 IP。一件事,我需要找到该接口名称并将其应用到我上面的代码中(或)是否有任何其他选项可以在没有该接口的情况下找到该 IP?

原文由 Smith Dwayne 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 690
1 个回答

无论接口名称是什么,我都想获得我的 IP 地址。

通过查看网络接口很难可靠地获取本地 IP 地址。正如您已经发现的,对于您运行的每个主机,网络接口名称可以是唯一的。更复杂的是,一台计算机可能有多个网络接口,每个接口都可能连接到互联网,也可能不连接到互联网。

您不需要使用默认界面。更简单的方法是让操作系统路由表为您解决问题。您可以通过设置与某个外部服务器的套接字连接然后调用 getsockname 来获取本地地址来做到这一点。此示例使用位于 8.8.8.8 的 Google 的 DNS 服务器来建立套接字连接,但您可以使用任何您喜欢的外部服务器。

 #include <iostream>     ///< cout
#include <cstring>      ///< memset
#include <errno.h>      ///< errno
#include <sys/socket.h> ///< socket
#include <netinet/in.h> ///< sockaddr_in
#include <arpa/inet.h>  ///< getsockname
#include <unistd.h>     ///< close

int main()
{
    const char* google_dns_server = "8.8.8.8";
    int dns_port = 53;

    struct sockaddr_in serv;
    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    //Socket could not be created
    if(sock < 0)
    {
        std::cout << "Socket error" << std::endl;
    }

    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = inet_addr(google_dns_server);
    serv.sin_port = htons(dns_port);

    int err = connect(sock, (const struct sockaddr*)&serv, sizeof(serv));
    if (err < 0)
    {
        std::cout << "Error number: " << errno
            << ". Error message: " << strerror(errno) << std::endl;
    }

    struct sockaddr_in name;
    socklen_t namelen = sizeof(name);
    err = getsockname(sock, (struct sockaddr*)&name, &namelen);

    char buffer[80];
    const char* p = inet_ntop(AF_INET, &name.sin_addr, buffer, 80);
    if(p != NULL)
    {
        std::cout << "Local IP address is: " << buffer << std::endl;
    }
    else
    {
        std::cout << "Error number: " << errno
            << ". Error message: " << strerror(errno) << std::endl;
    }

    close(sock);
    return 0;
}

原文由 Justin Randall 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题