取得系统中网卡MAC地址的三种方法

2016-02-19 21:31 4 1 收藏

下面图老师小编跟大家分享取得系统中网卡MAC地址的三种方法,一起来学习下过程究竟如何进行吧!喜欢就赶紧收藏起来哦~

【 tulaoshi.com - 编程语言 】

做好的程序员一如做人。多看多想或许他山之石可以攻玉,但永远不要成为代码的奴隶。 CKER
  原著:Borland
  Translated by CKER
  
  第一种方法使用Microsoft的Netbios API。 这是一套通过Winsock提供底层网络支持的命令。使用Netbios的最大缺点是您必须在系统中安装了Netbios服务(假如您在windows网络中启用了文件共享的话,这就不是问题了)。除此此外,这种方法又快又准确。
  
  Netbios API只包括了一个函数,就叫做Netbios。这个函数使用网络控制块(network control block)结构作为参数,这个结构告诉函数要做什么。结构的定义如下:
    typedef strUCt _NCB {
      UCHAR  ncb_command;
      UCHAR  ncb_retcode;
      UCHAR  ncb_lsn;
      UCHAR  ncb_num;
      PUCHAR ncb_buffer;
      Word   ncb_length;
      UCHAR  ncb_callname[NCBNAMSZ];
      UCHAR  ncb_name[NCBNAMSZ];
      UCHAR  ncb_rto;
      UCHAR  ncb_sto;
      void (CALLBACK *ncb_post) (struct _NCB *);
      UCHAR  ncb_lana_num;
      UCHAR  ncb_cmd_cplt;
  #ifdef _WIN64
      UCHAR  ncb_reserve[18];
  #else
      UCHAR  ncb_reserve[10];
  #endif
      HANDLE ncb_event;
  } NCB, *PNCB;
  
  
  
  重点在于ncb_command 成员。这个成员告诉Netbios该作什么。我们使用三个命令来探测MAC地址。他们在MSDN的定义如下:
  命令描述:
  NCBENUM Windows NT/2000: 列举系统中网卡的数量。使用此命令后,ncb_buffer成员指向由LANA_ENUM结构填充的缓冲区。
  NCBENUM 不是标准的 NetBIOS 3.0 命令。
  
  NCBRESET 重置网卡。网卡在接受新的NCB命令之前必须重置。
  NCBASTAT 接受本地或远程接口卡的状态。使用此命令后,ncb_buffer成员指向由ADAPTER_STATUS结构填充的缓冲区,随后是NAME_BUFFER结构的数组。
  
  下面就是取得您系统MAC地址的步骤:
  1》列举所有的接口卡。
  2》重置每块卡以取得它的正确信息。
  3》查询接口卡,取得MAC地址并生成标准的冒号分隔格式。
  
  下面就是实例源程序。
  netbios.cpp
  
  #include windows.h
  #include stdlib.h
  #include stdio.h
  #include iostream
  #include string
  
  using namespace std;
  #define bzero(thing,sz) memset(thing,0,sz)
  
  bool GetAdapterInfo(int adapter_num, string &mac_addr)
  {
    // 重置网卡,以便我们可以查询
    NCB Ncb;
    memset(&Ncb, 0, sizeof(Ncb));
    Ncb.ncb_command = NCBRESET;
    Ncb.ncb_lana_num = adapter_num;
    if (Netbios(&Ncb) != NRC_GOODRET) {
      mac_addr = "bad (NCBRESET): ";
      mac_addr += string(Ncb.ncb_retcode);
      return false;
    }
  
    // 预备取得接口卡的状态块
    bzero(&Ncb,sizeof(Ncb);
    Ncb.ncb_command = NCBASTAT;
    Ncb.ncb_lana_num = adapter_num;
    strcpy((char *) Ncb.ncb_callname, "*");
    struct ASTAT
    {
      ADAPTER_STATUS adapt;
  
       NAME_BUFFER NameBuff[30];
    } Adapter;
    bzero(&Adapter,sizeof(Adapter));
    Ncb.ncb_buffer = (unsigned char *)&Adapter;
    Ncb.ncb_length = sizeof(Adapter);
  
    // 取得网卡的信息,并且假如网卡正常工作的话,返回标准的冒号分隔格式。
    if (Netbios(&Ncb) == 0)
    {
      char acMAC[18];
      sprintf(acMAC, "%02X:%02X:%02X:%02X:%02X:%02X",
              int (Adapter.adapt.adapter_address[0]),
              int (Adapter.adapt.adapter_address[1]),
              int (Adapter.adapt.adapter_address[2]),
              int (Adapter.adapt.adapter_address[3]),
              int (Adapter.adapt.adapter_address[4]),
              int (Adapter.adapt.adapter_address[5]));
      mac_addr = acMAC;
      return true;
    }
    else
    {
      mac_addr = "bad (NCBASTAT): ";
      mac_addr += string(Ncb.ncb_retcode);
      return false;
    }
  }
  
  int main()
  {
    // 取得网卡列表
    LANA_ENUM AdapterList;
    NCB Ncb;
    memset(&Ncb, 0, sizeof(NCB));
    Ncb.ncb_command = NCBENUM;
    Ncb.ncb_buffer = (unsigned char *)&AdapterList;
    Ncb.ncb_length = sizeof(AdapterList);
    Netbios(&Ncb);
  
    // 取得本地以太网卡的地址
    string mac_addr;
    for (int i = 0; i AdapterList.length - 1; ++i)
    {
      if (GetAdapterInfo(AdapterList.lana[i], mac_addr))
      {
        cout "Adapter " int (AdapterList.lana[i])
                "'s MAC is " mac_addr endl;
      }
      else
      {
        cerr "Failed to get MAC address! Do you" endl;
        cerr "have the NetBIOS protocol installed?" endl;
        break;
      }
    }
  
    return 0;
  }
  
  
  file://---------------------------------------------------------------------------
  
  
  第二种方法-使用COM GUID API
  这种方法使用COM API创建一个GUID(全局唯一标识符)并从那里继续MAC地址。GUID通常用来标识COM组件以及系统中的其他对象。它们是由MAC地址(结合其他东西)计算得来的,表面上MAC地址就包含在其中。我说表面上是因为事实上并没有包含。
  
   我提供这种方法更多的是为了作为反面教材。您也许用这种方法能够得到MAC地址,但有时候您只会得到随机的十六进制数值。
  下面的例子十分简单,无需多讲。我们使用CoCreateGuid创建GUID,并将最后六个字节放入字符串中。它们可能是MAC地址,但并不是必然的。
  
  uuid.cpp
  #include windows.h
  #include iostream
  #include conio.h
  
  using namespace std;
  
  int main()
  {
      cout "MAC address is: ";
  
      // 向COM要求一个UUID。假如机器中有以太网卡,
      // UUID最后的六个字节(Data4的2-7字节)应该是本地以太网卡的MAC地址。
      GUID uuid;
      CoCreateGuid(&uuid);
      // Spit the address out
  &nbs

来源:http://www.tulaoshi.com/n/20160219/1626403.html

延伸阅读
标签: 老人 老年人
老人肾虚三种方法调理 肾虚指肾脏精气阴阳不足。肾虚的种类有很多,其中最常见的是肾阴虚、肾阳虚。无论肾阴虚还是肾阳虚,都会导致人体的免疫能力下降,危害到身体的健康,老年群体,由于机体功能的衰退,就更容易得肾虚了。面对老年人肾虚的问题可以通过3种方法来进行调理。 一、肾虚调理——饮食调补 ...
标签: 美容
三种方法轻松去眼袋http://www.69jk.cn 2014年02月18日 来源:互联网 每天早上醒来,最让人接受不了的就是看到镜子中的自己眼睛浮肿,重重的眼睛好像怎么也睁不开,看起来格外沧桑。应该怎么办?眼袋怎么去除才最有效呢?下面小编帮你总结几种好方法,快速摆脱眼袋困扰! ...
iphoneSE死机重启的三种方法   苹果iphoneSE死机怎么重启的三种方法 1)首先我们可以长按【电源键】10秒以上,一般情况下手机会自动重启,然后恢复。 2)长按电源键不管用的时候,我们就再同时长按【电源键】和【home键】5秒以上,手机即会被强制关机,关机后再重启即可。 3)有时候由于软件与系统不谦容出现特别严...
标签: 美容 美容方法
每位女生都希望自己的肌肤如剥壳鸡蛋一般光滑细腻,因为细腻肌肤不仅让你永远年轻,更能让你轻松上妆,久不脱妆!然而到底怎么做能拥有细嫩肌肤呢? 三种方法 拥有细嫩肌肤 朋友们都夸我的皮肤好,说我的皮肤白里透红,晶莹剔透,吹弹可破。嘻嘻,这些话我是最爱听得,听了以后心里就别提有多高兴了,其实你也可以有我这样...
标签: 分娩
推荐阅读:最容易犯的12个喂养错误 在家像只横行的小老虎,出门变成胆怯的小猫咪。一些家长常常说自己的孩子是“门背后的霸王”,并为此头疼不已。幼教专家提醒年轻父母:鼓励式教育最重要,改变宝宝行为有三大原则—— 在家别太宠溺 胆怯表现比较严重的孩子,往往在家中受到过多宠爱与纵容,与社会的接触欠缺,这不免使其对公...

经验教程

852

收藏

93
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部