Windows获取本机MAC地址方法(C语言)
Windows获取本机MAC地址方法(C语言)
用到的方法有两种:Netbios()和GetAdaptersInfo();
Netbios
获取步骤主要分为三步:
一、枚举本机所有LAN
二、重设每个LANA(初始化所有LANA)
三、获取网卡信息(填充数据结构)
如果只有单网卡的情况下,第一步可以不用有,但是在第三步之前一定要对所有的LANA进行重设即初始化。
实例代码如下:
#include
#include
#include
#include
#pragma comment(lib, "NetAPI32.Lib")
typedef struct _ASTAT_
{
ADAPTER_STATUS adapt; //包含一个网络适配器的信息
NAME_BUFFER NameBuff [30];
}ASTAT, * PASTAT; //定义一个网卡的结构体
//解释并执行指定的网络控制块(NCB)
int main (void)
{
NCB ncb; //网络控制块
ASTAT Adapter; //包含MAC地址的数据结构
LANA_ENUM lana_enum; //包含当前LAN适配器的数量
UCHAR uRetCode; //返回结果码
//UCHAR *mac={};
//用Netbios()获取网卡信息(MACIP网关…)的基本步骤:
//一、枚举本机所有LAN
//二、重设每个LANA(初始化所有LANA)
//三、获取网卡信息(填充数据结构)
//一、NCBENUM:枚举LAN适配器(LANA)号码
memset(&ncb, 0, sizeof(ncb));
memset(&lana_enum, 0, sizeof(lana_enum));
ncb.ncb_command = NCBENUM; //统计系统中网卡的数量 指定指令为NCBENUM,用于获取网卡的数量及编号 向网卡发送NCBENUM命令,以获取当前机器的网卡信息,如有多少个网卡,每个网卡的编号(MAC地址)
ncb.ncb_buffer = (unsigned char *)&lana_enum;
ncb.ncb_length = sizeof(LANA_ENUM);
uRetCode = Netbios(&ncb);
if(uRetCode != NRC_GOODRET)
exit(-1);
//二、NCBREST:重置LAN适配器
for(int lana=0; lana<lana_enum.length; lana++)
{
ncb.ncb_command = NCBRESET; //初始化逻辑网卡命令
ncb.ncb_lana_num = lana_enum.lana[lana];
uRetCode = Netbios(&ncb);
if(uRetCode == NRC_GOODRET)
break;
}
//三、NCBASTAT:检索本地或远程适配器的状态(lan_enum.lana[0]默认为本地PC的MAC)
memset(&ncb, 0, sizeof(ncb));
ncb.ncb_command = NCBASTAT; //对逻辑网卡统计信息命令
ncb.ncb_lana_num = lana_enum.lana[0]; //这里只获取了一个网卡的信息,如果要获取全部网卡的信息,可以把这一部分放入上面的循环语句中
strcpy((char*)ncb.ncb_callname, "*");
ncb.ncb_buffer = (unsigned char *)&Adapter; //绑定数据结构ncb 和 Adapter:填充Adapter
ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios(&ncb);
if(uRetCode != NRC_GOODRET)
exit(-1);
printf("MAC:X-X-X-X-X-Xn",
Adapter.adapt.adapter_address[0],
Adapter.adapt.adapter_address[1],
Adapter.adapt.adapter_address[2],
Adapter.adapt.adapter_address[3],
Adapter.adapt.adapter_address[4],
Adapter.adapt.adapter_address[5]);
}
GetAdaptrsInfo
GetAdaptersInfo的使用更简单,但是也存在系统兼容性问题,如果想要更稳定,建议使用GetAdaptersAddresses。下面程序中非常的简单,但是只针对单张网卡进行了设计,有多张网卡的时候就要进行区分了。
#pragma comment(lib,"Iphlpapi.lib")
#include
//#include
#include
int main()
{
DWORD dwRetVal = 0;
IP_ADAPTER_INFO adapterInfo ={0}; //存放网卡信息的数据结构
IP_ADAPTER_INFO *pAdapter = NULL; //指向该结构的指针
ULONG ulOutBufLen = sizeof(adapterInfo);
dwRetVal = GetAdaptersInfo(&adapterInfo, &ulOutBufLen); //获取网卡信息
if(dwRetVal == ERROR_SUCCESS)
{
pAdapter = &adapterInfo;
//printf("AdapterName:%sn",pAdapter->AdapterName);
//printf("AdapterDesc:%sn",pAdapter->Description);
printf("AdapterAddr:"); //MAC地址
for(UINT i=0;iAddressLength;i++)
{
printf("X%c", pAdapter->Address[i],
i == pAdapter->AddressLength-1 ? 'n' : '-');
}
printf("AdapterType:%dn",pAdapter->Type); //6是以太网网卡接口的意思
// printf("IPAddress:%sn",pAdapter->IpAddressList.IpAddress.String);
// printf("IPMask:%sn",pAdapter->IpAddressList.IpMask.String);
}
else if(ERROR_BUFFER_OVERFLOW == dwRetVal)//有多张网卡的时候出现的情况
printf("ERROR_BUFFER_OVERFLOWn ");
else
{
printf("GetAdaptersInfo() failed.");
//printf("error:%dn",dwRetVal);
}
return 0;
}
一台机器上可能不止有一个网卡,但每一个网卡只有一个MAC地址,而每一个网卡可能配置有多个IP地址;如平常的笔记本电脑中,就会有无线网卡和有线网卡(网线接口)两种;因此,如果要获得本机所有网卡的IP和MAC地址信息,则必须顺序获得每个网卡,再依次获取其信息等;在windows sdk中,用IP_ADAPTER_INFO结构体存储网卡信息,包括网卡名、网卡描述、网卡MAC地址、网卡IP等,该结构体的主要描述如下所示:
typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;//指向链表中下一个适配器信息的指针
DWORD ComboIndex;//预留值
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];//使用ANSI字符串表示的适配器名称
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];//使用ANSI字符串表示的适配器描述
UINT AddressLength;//适配器硬件地址以字节计算的长度
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];//硬件地址以BYTE数组所表示
DWORD Index;//适配器索引
UINT Type;//适配器类型,主要有以下几种:
/*
* MIB_IF_TYPE_OTHER 1
* MIB_IF_TYPE_ETHERNET 6
* MIB_IF_TYPE_TOKENRING 9
* MIB_IF_TYPE_FDDI 15
* MIB_IF_TYPE_PPP 23
* MIB_IF_TYPE_LOOPBACK 24
* MIB_IF_TYPE_SLIP 28
*/
UINT DhcpEnabled;//指定这个适配器是否开启DHCP
PIP_ADDR_STRING CurrentIpAddress;//预留值
IP_ADDR_STRING IpAddressList;//该适配器的IPv4地址链表
IP_ADDR_STRING GatewayList;//该适配器的网关IPv4地址链表
IP_ADDR_STRING DhcpServer;//该适配器的DHCP服务器的IPv4 地址链表
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO,*PIP_ADAPTER_INFO;