getifaddrs
函数用来获取本机网卡上ip地址信息,如下所示我们实现了一个工具类,并测试验证。
#include <string>
#include <vector>
#include <map>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <string.h>
struct IfaceIpInfo {
std::string ifName;
std::vector<std::string> ipv4;
std::vector<std::string> ipv6;
};
class IpTool {
public:
static bool FetchAllIpAddress(std::map<std::string, IfaceIpInfo> &local)
{
struct ifaddrs *ifaddr = nullptr;
struct ifaddrs *ifa = nullptr;
if (getifaddrs(&ifaddr) == -1) {
printf("getifaddrs failed, %s", strerror(errno));
return false;
}
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) {
continue;
}
int family = ifa->ifa_addr->sa_family;
if (family != AF_INET && family != AF_INET6) {
continue;
}
char addr[NI_MAXHOST] = {0};
int ret = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
addr, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST);
if (ret != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(ret));
freeifaddrs(ifaddr);
return false;
}
std::string ifName = ifa->ifa_name;
std::map<std::string, IfaceIpInfo>::iterator iter = local.find(ifName);
if (iter == local.end()) {
IfaceIpInfo tmp;
iter = local.emplace(ifName, tmp).first;
}
if (family == AF_INET) {
iter->second.ipv4.push_back(addr);
} else {
/* For an IPv6 address, the suffix %wlan0 exists. */
char *sepNum = strchr(addr, '%');
if (sepNum != nullptr) {
*sepNum = '\0';
}
iter->second.ipv6.push_back(addr);
}
}
freeifaddrs(ifaddr);
return true;
}
};
int main(void)
{
std::map<std::string, IfaceIpInfo> local;
if (!IpTool::FetchAllIpAddress(local)) {
printf("fetch ip address failed!");
return -1;
}
for (auto iter = local.begin(); iter != local.end(); ++iter) {
printf("iface [%s]\n", iter->first.c_str());
printf(" ipv4 address is [\n");
for (auto it = iter->second.ipv4.begin(); it != iter->second.ipv4.end(); ++it) {
printf(" %s\n", it->c_str());
}
printf("]\n ipv6 address is [\n");
for (auto it = iter->second.ipv6.begin(); it != iter->second.ipv6.end(); ++it) {
printf(" %s\n", it->c_str());
}
printf("]\n");
}
return 0;
}