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()获取网卡信息(MAC\IP\网关…)的基本步骤:
    //一、枚举本机所有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//初始化逻辑网卡命令
        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:%02X-%02X-%02X-%02X-%02X-%02X\n",    
        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:%s\n",pAdapter->AdapterName);  
        //printf("AdapterDesc:%s\n",pAdapter->Description);  
        printf("AdapterAddr:");  //MAC地址
        for(UINT i=0;iAddressLength;i++)  
        {  
            printf("%02X%c", pAdapter->Address[i],  
                i == pAdapter->AddressLength-1 ? '\n' : '-');  
        }  
        printf("AdapterType:%d\n",pAdapter->Type);  //6是以太网网卡接口的意思
       // printf("IPAddress:%s\n",pAdapter->IpAddressList.IpAddress.String);  
       // printf("IPMask:%s\n",pAdapter->IpAddressList.IpMask.String);  
    }  
    else if(ERROR_BUFFER_OVERFLOW == dwRetVal)//有多张网卡的时候出现的情况
        printf("ERROR_BUFFER_OVERFLOW\n ");

    else  
    {  
        printf("GetAdaptersInfo() failed.");  
        //printf("error:%d\n",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;

你可能感兴趣的:(window,API,C程序代码)