一、GetAdaptersInfo()和GetAdaptersAddresses()的区别
GetAdaptersInfo()
和 GetAdaptersAddresses()
是 Windows 系统中用于获取网络适配器信息的两个不同的API函数。
-
GetAdaptersInfo():
- 这是一个较旧的API函数,用于获取网络适配器列表及其相关信息。
- 它返回一个包含
IP_ADAPTER_INFO
结构的数组,每个结构代表一个网络适配器。 - 这些信息包括适配器名称、描述、索引、MAC地址、IP地址、子网掩码等。
- 由于
GetAdaptersInfo()
可能返回不完整的IPv6地址信息,因此它逐渐被GetAdaptersAddresses()
替代。
-
GetAdaptersAddresses():
- 这是一个更新的API函数,用于获取更全面的网络适配器信息,包括IPv4和IPv6地址。
- 它返回一个包含
IP_ADAPTER_ADDRESSES
结构的链表,每个结构代表一个网络适配器的地址信息。 - 这些信息包括适配器的索引、名称、描述、物理地址、IPv4地址、IPv6地址、DNS服务器列表等。
GetAdaptersAddresses()
支持更多的功能,例如获取链路本地地址和站点本地地址。
总的来说,GetAdaptersAddresses()
提供了比 GetAdaptersInfo()
更多的网络适配器信息,并且对IPv6有更好的支持。如果你的应用程序需要处理IPv6地址或者需要更详细的网络适配器信息,推荐使用 GetAdaptersAddresses()
。
二、获取网卡信息
1、GetAdaptersInfo()获取网卡信息,可用获取描述信息,但网卡名称不是可理解的
#include <WinSock2.h>
#include <Iphlpapi.h>
using namespace std;
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
void getAdapterInfo()
{
//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
PIP_ADAPTER_INFO pAdapter = NULL;
//得到结构体大小,用于GetAdaptersInfo参数
unsigned long stSize = sizeof(IP_ADAPTER_INFO);
//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
//记录网卡数量
int netCardNum = 0;
//记录每张网卡上的IP地址数量
int IPnumPerNetCard = 0;
if (ERROR_BUFFER_OVERFLOW == nRel)
{
//如果函数返回的是ERROR_BUFFER_OVERFLOW
//则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小
//这也是说明为什么stSize既是一个输入量也是一个输出量
//释放原来的内存空间
delete pIpAdapterInfo;
//重新申请内存空间用来存储所有网卡信息
pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
//再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量
nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
}
if (ERROR_SUCCESS == nRel)
{ //输出网卡信息,可能有多网卡,因此通过循环去判断
pAdapter = pIpAdapterInfo;
while (pAdapter)
{
qDebug() << QStringLiteral("网卡数量:") << ++netCardNum << endl;
qDebug() << QStringLiteral("网卡名称:") << pAdapter->AdapterName << endl;
qDebug() << QStringLiteral("网卡描述:") << pAdapter->Description << endl;
switch (pAdapter->Type)
{
case MIB_IF_TYPE_OTHER:
qDebug() << "网卡类型:" << "OTHER" << endl;
break;
case MIB_IF_TYPE_ETHERNET:
{//虚拟网卡也在此
qDebug() << "网卡类型:" << "ETHERNET" << endl;
}
break;
case MIB_IF_TYPE_TOKENRING:
qDebug() << "网卡类型:" << "TOKENRING" << endl;
break;
case MIB_IF_TYPE_FDDI:
qDebug() << "网卡类型:" << "FDDI" << endl;
break;
case MIB_IF_TYPE_PPP:
printf("PP\n");
qDebug() << "网卡类型:" << "PPP" << endl;
break;
case MIB_IF_TYPE_LOOPBACK:
qDebug() << "网卡类型:" << "LOOPBACK" << endl;
break;
case MIB_IF_TYPE_SLIP:
qDebug() << "网卡类型:" << "SLIP" << endl;
break;
default:
break;
}
qDebug() << "网卡MAC地址:";
for (DWORD i = 0; i < pAdapter->AddressLength; i++)
{
if (i < pAdapter->AddressLength - 1)
{
printf("%02X-", pAdapter->Address[i]);
}
else
{
printf("%02X\n", pAdapter->Address[i]);
}
}
qDebug() << "网卡IP地址如下:" << endl;
//可能网卡有多IP,因此通过循环去判断
QStringList ipAddrList;
IP_ADDR_STRING *pIpAddrString = &(pAdapter->IpAddressList);
IPnumPerNetCard = 0;
do
{
ipAddrList.append(pIpAddrString->IpAddress.String);
qDebug() << "该网卡上的IP数量:" << ++IPnumPerNetCard << endl;
qDebug() << "IP 地址:" << pIpAddrString->IpAddress.String << endl;
qDebug() << "子网地址:" << pIpAddrString->IpMask.String << endl;
qDebug() << "网关地址:" << pAdapter->GatewayList.IpAddress.String << endl;
pIpAddrString = pIpAddrString->Next;
} while (pIpAddrString);
if (getAdapterState(pAdapter->Index))
{
qDebug() << "网卡工作正常" << endl;
}
else
{
qDebug() << "网卡工作异常" << endl;
}
pAdapter = pAdapter->Next;
qDebug() << "--------------------------------------------------------------------" << endl;
}
}
//释放内存空间
if (pIpAdapterInfo)
{
delete[]pIpAdapterInfo;
pIpAdapterInfo = NULL;
}
}
bool getAdapterState(DWORD index)
{
MIB_IFROW Info; // 存放获取到的Adapter参数
memset(&Info, 0, sizeof(MIB_IFROW));
Info.dwIndex = index; // dwIndex是需要获取的Adapter的索引,可以通过GetAdaptersInfo和其他相关函数获取
if (GetIfEntry(&Info) != NOERROR)
{
printf("ErrorCode = %d\n", GetLastError());
return false;
}
if (Info.dwOperStatus == IF_OPER_STATUS_NON_OPERATIONAL
|| Info.dwOperStatus == IF_OPER_STATUS_UNREACHABLE
|| Info.dwOperStatus == IF_OPER_STATUS_DISCONNECTED
|| Info.dwOperStatus == IF_OPER_STATUS_CONNECTING)
{
return false;
}
else if (Info.dwOperStatus == IF_OPER_STATUS_OPERATIONAL
|| Info.dwOperStatus == IF_OPER_STATUS_CONNECTED)
{
return true;
}
return false;
}
2、GetAdaptersAddressesInfo():获取网卡信息,可获取描述信息,和可理解的网卡名称
#include <WinSock2.h>
#include <Iphlpapi.h>
using namespace std;
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
void GetAdaptersAddressesInfo()
{
ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
if (GetAdaptersAddresses(AF_INET, 0, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW)
{
free(pAddresses);
pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
}
if (GetAdaptersAddresses(AF_INET, 0, NULL, pAddresses, &outBufLen) == NO_ERROR)
{
PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
while (pCurrAddresses != NULL)
{
qDebug()<<"Friendly Name = "<< pCurrAddresses->FriendlyName;
qDebug() << pCurrAddresses->AdapterName;
qDebug() << pCurrAddresses->Description;
QString desStr = QString::fromWCharArray(pCurrAddresses->Description);
urrAddresses = pCurrAddresses->Next;
}
}
free(pAddresses);
}