GetAdaptersInfo 和 GetAdaptersAddresses 都能獲取網絡相關信息,如網卡名稱、MAC 地址、IP、DNS、網關等信息,但是兩個函數感覺都有一些問題,GetAdaptersInfo 獲取不到 IPV6 地址信息,使用起來較為簡單,GetAdaptersAddresses 可以獲取到 IPV6 地址信息,但是似乎獲取不到 子網掩碼 ,MSDN 推薦使用 GetAdaptersAddresses 。
1、GetAdaptersInfo:
代碼:
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD errValue = 0;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
if (!pAdapterInfo)//malloc失敗
return;
if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) //空間不夠,重新分配
{
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
if (!pAdapterInfo) //malloc失敗
return;
}
CString info;
if ((errValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
info += CString(_T("Adapter Name:")) + CString(pAdapter->AdapterName) + CString(_T("\r\n"));//名字
info += CString(_T("Adapter Desc:")) + CString(pAdapter->Description) + CString(_T("\r\n"));//描述
CString mac;
mac.Format(_T("%02X%02X%02X%02X%02X%02X"), pAdapter->Address[0], pAdapter->Address[1], \
pAdapter->Address[2], pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]);
info += CString(_T("Adapter Mac:")) + mac + CString(_T("\r\n"));//MAC地址
CString type;
switch (pAdapter->Type) //類型,列舉了幾種
{
case MIB_IF_TYPE_OTHER:
type = _T("其他");
break;
case MIB_IF_TYPE_ETHERNET:
type = _T("以太網接口");
break;
case IF_TYPE_ISO88025_TOKENRING:
type = _T("ISO88025令牌環");
break;
case MIB_IF_TYPE_PPP:
type = _T("PPP接口");
break;
case MIB_IF_TYPE_LOOPBACK:
type = _T("軟件回路接口");
break;
case MIB_IF_TYPE_SLIP:
type = _T("ATM網絡接口");
break;
case IF_TYPE_IEEE80211:
type = _T("無線網絡接口");
break;
default:
type = _T("未知接口");
break;
}
info += CString(_T("網卡類型:")) + type + CString(_T("\r\n"));
info += CString(_T("IP地址:")) + CString(pAdapter->IpAddressList.IpAddress.String) + CString(_T("\r\n"));
info += CString(_T("子網掩碼:")) + CString(pAdapter->IpAddressList.IpMask.String) + CString(_T("\r\n"));
info += CString(_T("默認網關:")) + CString(pAdapter->GatewayList.IpAddress.String) + CString(_T("\r\n"));
info += CString(_T("是否DHCP:")) + CString(pAdapter->DhcpEnabled ? _T("是") : _T("否")) + CString(_T("\r\n"));
info += CString(_T("DHCP地址:")) + CString(pAdapter->DhcpServer.IpAddress.String) + CString(_T("\r\n"));
//Dns
IP_PER_ADAPTER_INFO* pPerAdapt = NULL;
ULONG ulLen = 0;
int err = GetPerAdapterInfo(pAdapter->Index, pPerAdapt, &ulLen);
if (err == ERROR_BUFFER_OVERFLOW)
{
pPerAdapt = (IP_PER_ADAPTER_INFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLen);
err = GetPerAdapterInfo(pAdapter->Index, pPerAdapt, &ulLen);
if (err == ERROR_SUCCESS)
{
IP_ADDR_STRING* pNext = &(pPerAdapt->DnsServerList);
if (pNext && strcmp(pNext->IpAddress.String, "") != 0)//手動DNS
{
info = info + CString(_T("DNS:")) + CString(pNext->IpAddress.String) + _T("\r\n");
if (pNext->Next)
{
pNext = pNext->Next;
info = info + CString(_T("備用DNS:")) + CString(pNext->IpAddress.String) + _T("\r\n");
}
}
}
HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pPerAdapt);
}
info += "\r\n";
pAdapter = pAdapter->Next;
}
}
else
{
CString s;
s.Format(_T("GetAdaptersInfo failed with error: %d\r\n"), errValue);
info += s;
}
if (pAdapterInfo)
free(pAdapterInfo);
SetDlgItemText(IDC_EDIT, info);
效果:
2、GetAdaptersAddresses:
代碼:
//關於這個標志,查 MSDN 吧。。。
ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;//包括 IPV4 ,IPV6 網關
ULONG family = AF_UNSPEC;//返回包括 IPV4 和 IPV6 地址
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 0;
DWORD dwRetVal = 0;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
IP_ADAPTER_PREFIX *pPrefix = NULL;
outBufLen = 15000;
do
{
pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
if (pAddresses == NULL)
return;
dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW)
{
free(pAddresses);
pAddresses = NULL;
}
else
break;
} while (dwRetVal == ERROR_BUFFER_OVERFLOW);
CString info;
if (dwRetVal == NO_ERROR)
{
pCurrAddresses = pAddresses;
while (pCurrAddresses)
{
info += CString(_T("Adapter name:")) + pCurrAddresses->AdapterName + CString(_T("\r\n"));
info += CString(_T("Description:")) + CString(pCurrAddresses->Description) + CString(_T("\r\n"));
info += CString(_T("Friendly name:")) + CString(pCurrAddresses->FriendlyName) + CString(_T("\r\n"));
if (pCurrAddresses->PhysicalAddressLength != 0)
{
CString mac;//其實 MAC 地址的長度存在 PhysicalAddressLength 中,最好用它來確定格式化的長度
mac.Format(_T("%02X%02X%02X%02X%02X%02X"), pCurrAddresses->PhysicalAddress[0], pCurrAddresses->PhysicalAddress[1], \
pCurrAddresses->PhysicalAddress[2], pCurrAddresses->PhysicalAddress[3], pCurrAddresses->PhysicalAddress[4], \
pCurrAddresses->PhysicalAddress[5]);
info += CString(_T("Adapter Mac:")) + mac + CString(_T("\r\n"));//MAC地址
}
CString type;
switch (pCurrAddresses->IfType) //類型,列舉了幾種
{
case MIB_IF_TYPE_ETHERNET:
type = _T("以太網接口");
break;
case MIB_IF_TYPE_PPP:
type = _T("PPP接口");
break;
case MIB_IF_TYPE_LOOPBACK:
type = _T("軟件回路接口");
break;
case MIB_IF_TYPE_SLIP:
type = _T("ATM網絡接口");
break;
case IF_TYPE_IEEE80211:
type = _T("無線網絡接口");
break;
}
info += CString(_T("網卡類型:")) + type + CString(_T("\r\n"));
pUnicast = pCurrAddresses->FirstUnicastAddress;
while (pUnicast)//單播IP
{
CHAR IP[130] = { 0 };
if (AF_INET == pUnicast->Address.lpSockaddr->sa_family)// IPV4 地址,使用 IPV4 轉換
inet_ntop(PF_INET, &((sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr, IP, sizeof(IP));
else if (AF_INET6 == pUnicast->Address.lpSockaddr->sa_family)// IPV6 地址,使用 IPV6 轉換
inet_ntop(PF_INET6, &((sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr, IP, sizeof(IP));
info += CString(_T("單播IP:")) + CString(IP) + CString(_T("\r\n"));
pUnicast = pUnicast->Next;
}
if (pCurrAddresses->Dhcpv4Server.lpSockaddr)//DHCP服務器地址
{
CHAR dhcp[130] = { 0 };
if (AF_INET == pCurrAddresses->Dhcpv4Server.lpSockaddr->sa_family)
inet_ntop(PF_INET, &((sockaddr_in*)pCurrAddresses->Dhcpv4Server.lpSockaddr)->sin_addr, dhcp, sizeof(dhcp));
else if (AF_INET6 == pCurrAddresses->Dhcpv4Server.lpSockaddr->sa_family)
inet_ntop(PF_INET6, &((sockaddr_in6*)pCurrAddresses->Dhcpv4Server.lpSockaddr)->sin6_addr, dhcp, sizeof(dhcp));
info += CString(_T("DHCP地址:")) + CString(dhcp) + CString(_T("\r\n"));
}
pDnServer = pCurrAddresses->FirstDnsServerAddress;
while (pDnServer)//DNS
{
CHAR DNS[130] = { 0 };
if (AF_INET == pDnServer->Address.lpSockaddr->sa_family)
inet_ntop(PF_INET, &((sockaddr_in*)pDnServer->Address.lpSockaddr)->sin_addr, DNS, sizeof(DNS));
else if (AF_INET6 == pDnServer->Address.lpSockaddr->sa_family)
inet_ntop(PF_INET6, &((sockaddr_in6*)pDnServer->Address.lpSockaddr)->sin6_addr, DNS, sizeof(DNS));
info += CString(_T("DNS:")) + CString(DNS) + CString(_T("\r\n"));
pDnServer = pDnServer->Next;
}
CString MTU;// MTU
MTU.Format(_T("MTU:%d\r\n"), pCurrAddresses->Mtu);
info += MTU;
CString sendSpeend;//發送速率
sendSpeend.Format(_T("send speed:%d\r\n"), pCurrAddresses->TransmitLinkSpeed);
info += sendSpeend;
CString recvSpeed;//接收速率
recvSpeed.Format(_T("recv speed:%d\r\n"), pCurrAddresses->ReceiveLinkSpeed);
info += recvSpeed;
auto pGetway = pCurrAddresses->FirstGatewayAddress;
while (pGetway)//網關
{
CHAR getway[130] = { 0 };
if (AF_INET == pGetway->Address.lpSockaddr->sa_family)
inet_ntop(PF_INET, &((sockaddr_in*)pGetway->Address.lpSockaddr)->sin_addr, getway, sizeof(getway));
else if (AF_INET6 == pGetway->Address.lpSockaddr->sa_family)
inet_ntop(PF_INET6, &((sockaddr_in6*)pGetway->Address.lpSockaddr)->sin6_addr, getway, sizeof(getway));
info += CString(_T("Getway:")) + CString(getway) + CString(_T("\r\n"));
pGetway = pGetway->Next;
}
if (pCurrAddresses->Dhcpv6Server.lpSockaddr)//IPV6DHCP
{
CHAR dhcpv6[130] = { 0 };
if (AF_INET6 == pCurrAddresses->Dhcpv6Server.lpSockaddr->sa_family)
{
inet_ntop(PF_INET6, &((sockaddr_in6*)pCurrAddresses->Dhcpv6Server.lpSockaddr)->sin6_addr, dhcpv6, sizeof(dhcpv6));
info += CString(_T("DHCPV6:")) + CString(dhcpv6) + CString(_T("\r\n"));
}
}
info += CString(_T("\r\n"));
pCurrAddresses = pCurrAddresses->Next;
}
}
else
{
CString s;
s.Format(_T("GetAdaptersAddresses failed,error code:%d"), GetLastError());
AfxMessageBox(s);
}
if (pAddresses)
free(pAddresses);
SetDlgItemText(IDC_EDIT, info);
效果:
另外,使用 GetAdaptersAddresses 需要使用 iphlpapi.lib ,需要包含對應頭文件,使用 inet_ntop 轉換地址時需要包含 WS2tcpip.h 。
include <WS2tcpip.h>
include <iphlpapi.h>
pragma comment(lib, "iphlpapi.lib")
小結:
GetAdaptersInfo 使用較為簡單,大部分情況下可以滿足需求,GetAdaptersAddresses 使用復雜得多,但是可以獲取 IPV6 甚至組播地址等。
代碼鏈接:
VS2015工程:http://download.csdn.net/detail/yangyang031213/9891542
https://github.com/yangyang0312/cpp/tree/master/windows/AdaptInfo
————————————————
版權聲明:本文為CSDN博主「yangyang031213」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/yangyang031213/article/details/64906437