一台机器上可能有多个网卡,每一个网卡只有一个MAC地址,但是每一个网卡可能配置有多个IP地址;如平常的笔记本电脑中,就会有无线网卡和有线网卡(网线接口)两种;因此,如果要获得本机所有网卡的IP和MAC地址信息,则必须顺序获得每个网卡,再依次获取其信息等;在windows sdk中,用IP_ADAPTER_INFO结构体存储网卡信息,包括网卡名、网卡描述、网卡MAC地址、网卡IP等,该结构体的主要描述如下所示:
typedef struct _IP_ADAPTER_INFO
{
struct _IP_ADAPTER_INFO* Next; //指向同类型节点,即下一个网卡(如果有多个的话)
char AdapterName[MAX_ADAPTER_NAME_LENGTH +4]; //网卡名
charDescription[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; //网卡描述信息
UINT AddressLength; //网卡MAC长度
BYTEAddress[MAX_ADAPTER_ADDRESS_LENGTH]; //网卡MAC地址
IP_ADDR_STRING IpAddressList; //网卡IP列表
…………….
…………….
} IP_ADAPTER_INFO,
由于可能有多个网卡,因此struct _IP_ADAPTER_INFO* Next字段为一个链表结构指针,由于一个网卡可能有多个IP,因此IP_ADDR_STRING字段应该也是一个链表结构,其信息如下所示:
typedef struct _IP_ADDR_STRING
{
struct _IP_ADDR_STRING* Next; //指向同类型节点,即下一个IP(如果有多IP的话)
IP_ADDRESS_STRING IpAddress; //IP地址信息
IP_MASK_STRING IpMask;
DWORD Context;
} IP_ADDR_STRING,
IP_ADDR_STRING结构也是一个链表节点
综上所述,用下图来描述网卡的结构存储信息,也许更明朗:
-----------------------------------------------------------------------------------------------------------------------------------
直接上代码(注意代码工程需要链接Iphlpapi.lib库):
// 头文件包含 #include " stdafx.h " #include < WinSock2.h > #include < Iphlpapi.h > #include < iostream > using namespace std; // 函数声明 void output(PIP_ADAPTER_INFO pIpAdapterInfo); // 程序入口 int _tmain( int argc, _TCHAR * argv[]) { // PIP_ADAPTER_INFO结构体指针存储本机网卡信息 PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO(); // 得到结构体大小,用于GetAdaptersInfo参数 unsigned long stSize = sizeof (IP_ADAPTER_INFO); // 调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量 int nRel = GetAdaptersInfo(pIpAdapterInfo, & stSize); 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) { // 输出网卡信息 output(pIpAdapterInfo); } // 释放内存空间 if (pIpAdapterInfo) { delete pIpAdapterInfo; } getchar(); return 0 ; } /// 函数作用,输出网卡信息 void output(PIP_ADAPTER_INFO pIpAdapterInfo) { // 可能有多网卡,因此通过循环去判断 while (pIpAdapterInfo) { cout << " 网卡名称: " << pIpAdapterInfo -> AdapterName << endl; cout << " 网卡描述: " << pIpAdapterInfo -> Description << endl; cout << " 网卡MAC地址: " << pIpAdapterInfo -> Address; for (UINT i = 0 ; i < pIpAdapterInfo -> AddressLength; i ++ ) if (i == pIpAdapterInfo -> AddressLength - 1 ) { printf( " %02x\n " , pIpAdapterInfo -> Address[i]); } else { printf( " %02x- " , pIpAdapterInfo -> Address[i]); } cout << " 网卡IP地址如下: " << endl; // 可能网卡有多IP,因此通过循环去判断 IP_ADDR_STRING * pIpAddrString =& (pIpAdapterInfo -> IpAddressList); do { cout << pIpAddrString -> IpAddress.String << endl; pIpAddrString = pIpAddrString -> Next; } while (pIpAddrString); pIpAdapterInfo = pIpAdapterInfo -> Next; cout << " ***************************************************** " << endl; } return ; }
程序运行结果如下图所示:
- 获取MAC地址
-
[cpp]
// 定义网卡类型
typedef DWORD BFSYS_MAC_T;
#define BFSYS_MAC_ALL 0xFFFFFFFF // 所有网卡
#define BFSYS_MAC_PHYSICAL 0x00000001 // 物理网卡
#define BFSYS_MAC_WIRELESS 0x00000002 // 无线网卡
#define BFSYS_MAC_VIRTUAL 0x00000004 // 虚拟网卡(比如虚拟机带的虚拟网卡)
#define BFSYS_MAC_UNKNOWN 0x80000000 // 未知类型网卡
// 定义网卡MAC地址结构及数组
typedef struct _BFMAC_ADDR_STR_
{
BFSYS_MAC_T Type;
DWORD AddressLength;
BYTE Address[32];
}BFMACADDR, *PBFMACADDR;
typedef vector<BFMACADDR> BFMacAddrArray;
// 取得网卡地址信息,返回对应类型网卡的总数量
BFLIB_API
DWORD
BF_GetMacAddr(
IN BFSYS_MAC_T type, // 待取得网卡类型
OUT BFMacAddrArray *pAddrAry = NULL // 输出对应网卡类型的地址信息
);// 定义网卡类型
typedef DWORD BFSYS_MAC_T;
#define BFSYS_MAC_ALL 0xFFFFFFFF // 所有网卡
#define BFSYS_MAC_PHYSICAL 0x00000001 // 物理网卡
#define BFSYS_MAC_WIRELESS 0x00000002 // 无线网卡
#define BFSYS_MAC_VIRTUAL 0x00000004 // 虚拟网卡(比如虚拟机带的虚拟网卡)
#define BFSYS_MAC_UNKNOWN 0x80000000 // 未知类型网卡// 定义网卡MAC地址结构及数组
typedef struct _BFMAC_ADDR_STR_
{
BFSYS_MAC_T Type;
DWORD AddressLength;
BYTE Address[32];
}BFMACADDR, *PBFMACADDR;
typedef vector<BFMACADDR> BFMacAddrArray;// 取得网卡地址信息,返回对应类型网卡的总数量
BFLIB_API
DWORD
BF_GetMacAddr(
IN BFSYS_MAC_T type, // 待取得网卡类型
OUT BFMacAddrArray *pAddrAry = NULL // 输出对应网卡类型的地址信息
);
[cpp]
// 取得网卡地址信息,返回对应类型网卡的总数量
BFLIB_API
DWORD
BF_GetMacAddr(
IN BFSYS_MAC_T type, // 待取得网卡类型
OUT BFMacAddrArray *pAddrAry // 输出对应网卡类型的地址信息
)
{
// 清除上次信息
if (pAddrAry != NULL)
{
pAddrAry->clear();
}
// 获取Adapter信息
ULONG ulSize = sizeof(IP_ADAPTER_INFO);
BYTE *pBuf = new BYTE[ulSize];
if (pBuf == NULL)
{
return 0;
}
PIP_ADAPTER_INFO pIPAdapterInfo = (PIP_ADAPTER_INFO)pBuf;
DWORD dwRet = ::GetAdaptersInfo(pIPAdapterInfo, &ulSize);
// 缓冲区溢出则重新申请内存
if (ERROR_BUFFER_OVERFLOW == dwRet)
{
delete[] pBuf ;
pBuf = NULL;
pIPAdapterInfo = NULL;
pBuf = new BYTE[ulSize];
if (pBuf == NULL)
{
return 0;
}
pIPAdapterInfo = (PIP_ADAPTER_INFO)pBuf;
dwRet = ::GetAdaptersInfo(pIPAdapterInfo, &ulSize);
}
// 获取Adapter信息失败
if (dwRet != ERROR_SUCCESS)
{
delete[] pBuf;
pBuf = NULL;
pIPAdapterInfo = NULL;
return 0;
}
// 遍历所有网卡信息
DWORD dwTotalCount = 0;
BFMACADDR MacAddr;
while (pIPAdapterInfo != NULL)
{
// 得到MAC地址信息
memset(&MacAddr, 0, sizeof(MacAddr));
MacAddr.AddressLength = pIPAdapterInfo->AddressLength;
for (UINT i=0; i<pIPAdapterInfo->AddressLength; i++)
{
MacAddr.Address[i] = pIPAdapterInfo->Address[i];
}
// 是否无线网卡
if (pIPAdapterInfo->Type == 71)
{
MacAddr.Type = BFSYS_MAC_WIRELESS;
}
// 是否物理网卡
else if ( pIPAdapterInfo->Type == MIB_IF_TYPE_ETHERNET
&& strstr(pIPAdapterInfo->Description, "PCI") > 0
)
{
MacAddr.Type = BFSYS_MAC_PHYSICAL;
}
// 是否虚拟网卡
else if ( pIPAdapterInfo->Type == MIB_IF_TYPE_ETHERNET
&& strstr(pIPAdapterInfo->Description, "Virtual") > 0
)
{
MacAddr.Type = BFSYS_MAC_VIRTUAL;
}
// 其他网卡
else
{
MacAddr.Type = BFSYS_MAC_UNKNOWN;
}
// 是否需要的网卡类型
if ((type & MacAddr.Type) == MacAddr.Type)
{
dwTotalCount += 1;
if (pAddrAry != NULL)
{
pAddrAry->push_back(MacAddr);
}
}
// 遍历下一个Adapter
pIPAdapterInfo = pIPAdapterInfo->Next;
}
// 释放内存
delete[] pBuf;
pBuf = NULL;
pIPAdapterInfo = NULL;
// 返回获取到的数量
return dwTotalCount;
}// 取得网卡地址信息,返回对应类型网卡的总数量
BFLIB_API
DWORD
BF_GetMacAddr(
IN BFSYS_MAC_T type, // 待取得网卡类型
OUT BFMacAddrArray *pAddrAry // 输出对应网卡类型的地址信息
)
{
// 清除上次信息
if (pAddrAry != NULL)
{
pAddrAry->clear();
}// 获取Adapter信息
ULONG ulSize = sizeof(IP_ADAPTER_INFO);
BYTE *pBuf = new BYTE[ulSize];
if (pBuf == NULL)
{
return 0;
}
PIP_ADAPTER_INFO pIPAdapterInfo = (PIP_ADAPTER_INFO)pBuf;
DWORD dwRet = ::GetAdaptersInfo(pIPAdapterInfo, &ulSize);// 缓冲区溢出则重新申请内存
if (ERROR_BUFFER_OVERFLOW == dwRet)
{
delete[] pBuf ;
pBuf = NULL;
pIPAdapterInfo = NULL;
pBuf = new BYTE[ulSize];
if (pBuf == NULL)
{
return 0;
}
pIPAdapterInfo = (PIP_ADAPTER_INFO)pBuf;
dwRet = ::GetAdaptersInfo(pIPAdapterInfo, &ulSize);
}// 获取Adapter信息失败
if (dwRet != ERROR_SUCCESS)
{
delete[] pBuf;
pBuf = NULL;
pIPAdapterInfo = NULL;
return 0;
}// 遍历所有网卡信息
DWORD dwTotalCount = 0;
BFMACADDR MacAddr;
while (pIPAdapterInfo != NULL)
{
// 得到MAC地址信息
memset(&MacAddr, 0, sizeof(MacAddr));
MacAddr.AddressLength = pIPAdapterInfo->AddressLength;
for (UINT i=0; i<pIPAdapterInfo->AddressLength; i++)
{
MacAddr.Address[i] = pIPAdapterInfo->Address[i];
}// 是否无线网卡
if (pIPAdapterInfo->Type == 71)
{
MacAddr.Type = BFSYS_MAC_WIRELESS;
}
// 是否物理网卡
else if ( pIPAdapterInfo->Type == MIB_IF_TYPE_ETHERNET
&& strstr(pIPAdapterInfo->Description, "PCI") > 0
)
{
MacAddr.Type = BFSYS_MAC_PHYSICAL;
}
// 是否虚拟网卡
else if ( pIPAdapterInfo->Type == MIB_IF_TYPE_ETHERNET
&& strstr(pIPAdapterInfo->Description, "Virtual") > 0
)
{
MacAddr.Type = BFSYS_MAC_VIRTUAL;
}
// 其他网卡
else
{
MacAddr.Type = BFSYS_MAC_UNKNOWN;
}// 是否需要的网卡类型
if ((type & MacAddr.Type) == MacAddr.Type)
{
dwTotalCount += 1;
if (pAddrAry != NULL)
{
pAddrAry->push_back(MacAddr);
}
}// 遍历下一个Adapter
pIPAdapterInfo = pIPAdapterInfo->Next;
}// 释放内存
delete[] pBuf;
pBuf = NULL;
pIPAdapterInfo = NULL;// 返回获取到的数量
return dwTotalCount;
}
需要使用到#include <Iphlpapi.h>
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库