Linux/Windows枚举主机IP和MAC等网卡信息
#include <string>
#include <vector>
#ifdef _MSC_VER
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif // !_WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#include <iphlpapi.h>
#pragma comment(lib, "Iphlpapi.lib")
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <limits.h>
#endif
#pragma pack(1)
typedef struct __xxx__ { uint8_t v; }__xxx__;
typedef struct netcardinfo {
char ip[16];
char mac[6];
char ifname[512];
char ifdesc[512];
char netmask[16];
}netcardinfo;
#pragma pack()
class SockUtil {
public:
#ifdef _MSC_VER
WSADATA wsadata = { 0 };
#endif
SockUtil()
{
#ifdef _MSC_VER
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0)
{
std::cout << "Initialize winsock library failed!" << std::endl;
}
else
{
std::cout << "Initialize winsock library ok!" << std::endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
{
std::cout << "Winsock library version failed!" << std::endl;
WSACleanup();
}
else
{
std::cout << "Winsock library version ok!" << std::endl;
}
#endif
}
~SockUtil()
{
#ifdef _MSC_VER
WSACleanup();
#endif
}
private:
int enum_host_addr(std::vector<std::string>& sv, int af/*= AF_INET or AF_INET6*/)
{
int ret = 0;
char ip[65] = { 0 };
struct sockaddr_in* addr = nullptr;
#ifdef _MSC_VER
char host_name[33] = { 0 };
struct addrinfo hints = { 0 };
struct addrinfo* res = nullptr;
struct addrinfo* cur = nullptr;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = af; /* Allow IPv4 */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_socktype = SOCK_STREAM;
ret = gethostname(host_name, sizeof(host_name) / sizeof(*host_name));
if (ret == 0)
{
ret = getaddrinfo(host_name, nullptr, &hints, &res);
if (ret == 0) {
for (cur = res; cur != nullptr; cur = cur->ai_next) {
addr = (struct sockaddr_in*)cur->ai_addr;
inet_ntop(af, &addr->sin_addr, ip, sizeof(ip) / sizeof(*ip));
//std::cout << ip << std::endl;
sv.emplace_back(ip);
}
freeaddrinfo(res);
}
}
#else
struct ifaddrs* ifa = nullptr;
struct ifaddrs* oifa = nullptr;
ret = getifaddrs(&ifa);
if (ret == 0)
{
oifa = ifa;
while (ifa != nullptr)
{
// IPv4 排除localhost
if (ifa->ifa_addr != nullptr
&& ifa->ifa_addr->sa_family == af
&& strncmp(ifa->ifa_name, "lo", 2) != 0)
{
addr = (struct sockaddr_in*)ifa->ifa_addr;
inet_ntop(af, &addr->sin_addr, ip, sizeof(ip) / sizeof(*ip));
//std::cout << ip << std::endl;
sv.emplace_back(ip);
}
ifa = ifa->ifa_next;
}
freeifaddrs(oifa);
}
#endif
return ret;
}
public:
int enum_host_addr_ipv4(std::vector<std::string>& sv)
{
return enum_host_addr(sv, AF_INET);
}
int enum_host_addr_ipv6(std::vector<std::string>& sv)
{
return enum_host_addr(sv, AF_INET6);
}
int enum_host_mac_addr_ipv4(std::vector<netcardinfo>&vNetcardInfo)
{
#ifndef _MSC_VER
int s = (-1);
int ifc_num = 0;
struct ifreq ifr = { 0 };
struct ifconf ifc = { 0 };
struct ifreq buf[64] = { 0 };
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (s == -1)
{
printf("socket error\n");
goto __leave_clean__;
}
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t)buf;
if (ioctl(s, SIOCGIFCONF, &ifc) == -1)
{
printf("ioctl error\n");
goto __leave_clean__;
}
ifc_num = ifc.ifc_len / sizeof(struct ifreq);
while ((ifc_num--) > 0)
{
struct ifreq& ifr_it = buf[ifc_num];
if (ioctl(s, SIOCGIFFLAGS, &ifr_it) == 0)
{
if ((ifr_it.ifr_flags & IFF_LOOPBACK) != IFF_LOOPBACK)
{
// don't need loopback
netcardinfo nci = { 0 };
strcpy(nci.ifname, ifr_it.ifr_name);
strcpy(nci.ifdesc, ifr_it.ifr_name);
if (ioctl(s, SIOCGIFHWADDR, &ifr_it) == 0)
{
memcpy(nci.mac, ifr_it.ifr_ifru.ifru_hwaddr.sa_data, sizeof(nci.mac));
if (ioctl(s, SIOCGIFADDR, (char*)&ifr_it) == 0)
{
snprintf(nci.ip, sizeof(nci.ip)/sizeof(*nci.ip), "%s", (char*)inet_ntoa(((struct sockaddr_in*)&(ifr_it.ifr_addr))->sin_addr));
if (ioctl(s, SIOCGIFNETMASK, (char*)&ifr_it) == 0)
{
snprintf(nci.netmask, sizeof(*nci.netmask), "%s", (char*)inet_ntoa(((struct sockaddr_in*)&(ifr_it.ifr_netmask))->sin_addr));
vNetcardInfo.emplace_back(nci);
}
}
}
}
}
else
{
printf("get if flags error\n");
goto __leave_clean__;
}
}
__leave_clean__:
if (s != (-1))
{
shutdown(s, SHUT_RDWR);
close(s);
}
#else
ULONG nIpAdapterInfoSize = 0;
IP_ADAPTER_INFO* pIpAdapterInfo = NULL;
int IPnumPerNetCard = 0;
if ((::GetAdaptersInfo(NULL, &nIpAdapterInfoSize) == ERROR_BUFFER_OVERFLOW) && (nIpAdapterInfoSize > 0))
{
pIpAdapterInfo = (IP_ADAPTER_INFO*)malloc(nIpAdapterInfoSize);
if (pIpAdapterInfo != NULL)
{
if (::GetAdaptersInfo(pIpAdapterInfo, &nIpAdapterInfoSize) == ERROR_SUCCESS)
{
IP_ADAPTER_INFO* pIter = pIpAdapterInfo;
while (pIter)
{
IP_ADDR_STRING* pIpAddressList = &(pIter->IpAddressList);
while (pIpAddressList)
{
netcardinfo nci = { 0 };
if (pIpAdapterInfo->AddressLength == sizeof(nci.mac) / sizeof(*nci.mac))
{
strcpy(nci.ifname, pIter->AdapterName);
strcpy(nci.ifdesc, pIter->Description);
memcpy(nci.mac, pIter->Address, pIter->AddressLength);
strcpy(nci.ip, pIpAddressList->IpAddress.String);
strcpy(nci.netmask, pIpAddressList->IpMask.String);
vNetcardInfo.emplace_back(nci);
}
pIpAddressList = pIpAddressList->Next;
}
pIter = pIter->Next;
}
}
free(pIpAdapterInfo);
pIpAdapterInfo = NULL;
}
}
#endif // !_MSC_VER
return 0;
}
public:
static SockUtil* Inst()
{
static SockUtil SockUtilInstance;
return &SockUtilInstance;
}
};