我有一个获取本地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;
}
Run Code Online (Sandbox Code Playgroud)
所以我的结果是
lo =1 127.0.0.1
enp2s0 =1 172.20.55.6
172.20.55.6
Run Code Online (Sandbox Code Playgroud)
但是在另一台计算机上,接口名称是不同的。他们得到像波纹管一样的结果,
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)
Run Code Online (Sandbox Code Playgroud)
无论接口名称是什么,我都想获取我的Ip地址。如果接口名称与其他计算机不同,如何获取本地IP地址。无论接口名称是什么,都应该给ip地址。我怎样才能做到这一点?
我的问题是,现在我从这种方法获取本地IP。但是无论接口名称是什么,我都应该获得IP。一件事,我需要找到该接口名称并将其应用到我的上面的代码中(或)是否有其他选择来找到没有该接口的IP?
这些答案似乎都不够好:要么浏览界面太麻烦,要么需要连接到互联网。
这是一种基于 Justin Randall 的回答的方法。它基本相同,但它连接的是 UDP 套接字而不是 TCP。根据udp(7),connect(3)
在未绑定的 UDP 套接字上使用:
将自动分配一个空闲的本地端口 [...] 并将套接字绑定到 INADDR_ANY
此外,与 TCP 套接字相反,UDP 套接字上的 connect(3) 不存在任何网络开销或通信,因为它仅更改有关丢弃哪些数据包以及保留在套接字缓冲区中的数据包的规则。
因此,连接到任何INADDR_LOOPBACK
不足以检索已选择绑定套接字的本地地址的IP 地址。
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
int main(void) {
int sock = socket(PF_INET, SOCK_DGRAM, 0);
sockaddr_in loopback;
if (sock == -1) {
std::cerr << "Could not socket\n";
return 1;
}
std::memset(&loopback, 0, sizeof(loopback));
loopback.sin_family = AF_INET;
loopback.sin_addr.s_addr = 1337; // can be any IP address
loopback.sin_port = htons(9); // using debug port
if (connect(sock, reinterpret_cast<sockaddr*>(&loopback), sizeof(loopback)) == -1) {
close(sock);
std::cerr << "Could not connect\n";
return 1;
}
socklen_t addrlen = sizeof(loopback);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&loopback), &addrlen) == -1) {
close(sock);
std::cerr << "Could not getsockname\n";
return 1;
}
close(sock);
char buf[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &loopback.sin_addr, buf, INET_ADDRSTRLEN) == 0x0) {
std::cerr << "Could not inet_ntop\n";
return 1;
} else {
std::cout << "Local ip address: " << buf << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
无论接口名称是什么,我都想获取我的IP地址。
通过查看网络接口很难可靠地获取本地ip地址。正如您已经发现的那样,网络接口名称对于您在其上运行的每个主机可以是唯一的。为了使事情更加复杂,计算机可能具有多个网络接口,并且每个网络接口可能连接也可能不连接到Internet。
您无需使用默认界面。一种更简单的方法是让OS路由表为您解决。您可以通过建立与某些外部服务器的套接字连接,然后调用getsockname
以获取本地地址来完成此操作。此示例使用Google的DNS服务器8.8.8.8
建立套接字连接,但是您可以使用任何所需的外部服务器。
#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;
}
Run Code Online (Sandbox Code Playgroud)