C/C++获取主机网卡MAC地址的三方法

  MAC地址(Media Access Control address),又称为物理地址或硬件地址,是网络适配器(网卡)在制造时被分配的全球唯一的48位地址。这个地址是数据链路层(OSI模型的第二层)的一部分,用于在局域网(LAN)中唯一标识网络设备。获取网卡地址主要用于网络标识和身份验证的目的。MAC地址是一个唯一的硬件地址,通常由网卡的制造商在制造过程中分配。通过获取MAC地址可以判断当前主机的唯一性可以与IP地址绑定并实现网络准入控制。

  在Windows平台下获取MAC地址的方式有很多,获取MAC地址的常见方式包括使用操作系统提供的网络API(如Windows的GetAdaptersAddresses和GetAdaptersInfo),NetBIOS API,系统命令(如ipconfig /all),ARP缓存表查询,第三方库(如WinPcap或Libpcap),以及在编程语言中使用网络库。

  首先第一种获取方法封装函数,该功能的实现通过调用系统中的获取计算机的MAC地址。

  该函数首先分配内存来存储适配器信息,然后调用 GetAdaptersAddresses 函数获取适配器信息。如果内存不足,它会重新分配足够的内存并再次调用该函数。接着,它遍历返回的适配器信息,找到第一个物理地址长度为6的适配器,然后将其MAC地址以格式化字符串的形式存储在传入的 macOUT 变量中。最后,释放分配的内存,并返回一个布尔值。

  #include

  #include

  #include

  #include

  #pragma comment(lib, "Netapi32.lib")

  #pragma comment(lib, "IPHLPAPI.lib")

  using namespace std;

  bool GetMacByGetAdaptersAddresses(std::string& macOUT)

  {

  bool ret = false;

  ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES);

  PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);

  if (pAddresses == NULL)

  return false;

  if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW)

  {

  free(pAddresses);

  pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);

  if (pAddresses == NULL)

  return false;

  }

  if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == NO_ERROR)

  {

  for (PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses != NULL; pCurrAddresses = pCurrAddresses->Next)

  {

  // 确保MAC地址的长度为 00-00-00-00-00-00

  if (pCurrAddresses->PhysicalAddressLength != 6)

  continue;

  char acMAC[32];

  sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",

  int(pCurrAddresses->PhysicalAddress[0]),

  int(pCurrAddresses->PhysicalAddress[1]),

  int(pCurrAddresses->PhysicalAddress[2]),

  int(pCurrAddresses->PhysicalAddress[3]),

  int(pCurrAddresses->PhysicalAddress[4]),

  int(pCurrAddresses->PhysicalAddress[5]));

  macOUT = acMAC;

  ret = true;

  break;

  }

  }

  free(pAddresses);

  return ret;

  }

  int main(int argc, char *argv[])

  {

  std::string refBuffer;

  GetMacByGetAdaptersAddresses(refBuffer);

  std::cout << "Mac地址: " << refBuffer << std::endl;

  system("pause");

  return 0;

  }

  第二种方式函数,通过调用系统的获取计算机的主网卡的MAC地址。函数首先分配内存来存储适配器信息,然后调用获取适配器信息。如果内存不足,它会重新分配足够的内存并再次调用该函数。接着,它遍历返回的适配器信息,找到第一个类型为以太网且物理地址长度为6的适配器,然后将其MAC地址以格式化字符串的形式存储在传入的变量中。最后,释放分配的内存,并返回一个布尔值。

  #define _CRT_SECURE_NO_WARNINGS

  #define _WIN32_DCOM

  #define _CRT_NONSTDC_NO_DEPRECATE

  #include

  #include

  #include

  #include

  #pragma comment(lib, "Netapi32.lib")

  #pragma comment(lib, "IPHLPAPI.lib")

  using namespace std;

  bool GetMacByGetAdaptersInfo(std::string& macOUT)

  {

  bool ret = false;

  ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);

  PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));

  if (pAdapterInfo == NULL)

  return false;

  if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)

  {

  free(pAdapterInfo);

  pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);

  if (pAdapterInfo == NULL)

  return false;

  }

  if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR)

  {

  for (PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next)

  {

  // 确保是以太网

  if (pAdapter->Type != MIB_IF_TYPE_ETHERNET)

  continue;

  // 确保MAC地址的长度为 00-00-00-00-00-00

  if (pAdapter->AddressLength != 6)

  continue;

  char acMAC[32];

  sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",

  int(pAdapter->Address[0]),

  int(pAdapter->Address[1]),

  int(pAdapter->Address[2]),

  int(pAdapter->Address[3]),

  int(pAdapter->Address[4]),

  int(pAdapter->Address[5]));

  macOUT = acMAC;

  ret = true;

  break;

  }

  }

  free(pAdapterInfo);

  return ret;

  }

  int main(int argc, char *argv[])

  {

  std::string refBuffer;

  GetMacByGetAdaptersInfo(refBuffer);

  std::cout << "Mac地址: " << refBuffer << std::endl;

  system("pause");

  return 0;

  }

  第三种封装一个函数,其使用获取指定适配器号的MAC地址。函数首先通过命令重置指定网卡以便进行查询。接着,使用命令获取接口卡的状态块,其中包含了适配器的物理地址。如果调用成功,将适配器的地址以格式化字符串的形式存储在传入的变量中,最后返回一个布尔值。

  #include

  #include

  #include

  #include

  #pragma comment(lib, "Netapi32.lib")

  #pragma comment(lib, "IPHLPAPI.lib")

  using namespace std;

  bool GetAdapterInfo(int adapterNum, std::string& macOUT)

  {

  NCB Ncb;

  memset(&Ncb, 0, sizeof(Ncb));

  // 重置网卡 以便我们可以查询

  Ncb.ncb_command = NCBRESET;

  Ncb.ncb_lana_num = adapterNum;

  if (Netbios(&Ncb) != NRC_GOODRET)

  return false;

  // 准备取得接口卡的状态块

  memset(&Ncb, sizeof(Ncb), 0);

  Ncb.ncb_command = NCBASTAT;

  Ncb.ncb_lana_num = adapterNum;

  strcpy((char*)Ncb.ncb_callname, "*");

  struct ASTAT

  {

  ADAPTER_STATUS adapt;

  NAME_BUFFER nameBuff[30];

  }adapter;

  memset(&adapter, sizeof(adapter), 0);

  Ncb.ncb_buffer = (unsigned char*)&adapter;

  Ncb.ncb_length = sizeof(adapter);

  if (Netbios(&Ncb) != 0)

  return false;

  char acMAC[32];

  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]));

  macOUT = acMAC;

  return true;

  }

  bool GetMacByNetBIOS(std::string& macOUT)

  {

  // 取得网卡列表

  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);

  // 取得MAC

  for (int i = 0; i < adapterList.length; ++i)

  {

  if (GetAdapterInfo(adapterList.lana[i], macOUT))

  return true;

  }

  return false;

  }

  int main(int argc, char *argv[])

  {

  std::string refBuffer;

  GetMacByNetBIOS(refBuffer);

  std::cout << "Mac地址: " << refBuffer << std::endl;

  system("pause");

  return 0;

  }

  三种方式均可以输出系统的MAC地址,可根据自己的需求选择;

  以上就是C/C++获取主机网卡MAC地址的三方法的详细内容,更多关于C/C++ 获取MAC地址的资料请关注脚本之家其它相关文章!

  您可能感兴趣的文章: