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),以及在编程语言中使用网络库。
首先第一种获取方法封装GetMacByGetAdaptersAddresses函数,该功能的实现通过调用系统中的GetAdaptersAddresses获取计算机的MAC地址。
该函数首先分配内存来存储适配器信息,然后调用 GetAdaptersAddresses 函数获取适配器信息。如果内存不足,它会重新分配足够的内存并再次调用该函数。接着,它遍历返回的适配器信息,找到第一个物理地址长度为6的适配器,然后将其MAC地址以格式化字符串的形式存储在传入的 macOUT 变量中。最后,释放分配的内存,并返回一个布尔值。
#include <iostream>
#include <winsock2.h>
#include <iphlpapi.h>
#include <string>
#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;
}
第二种方式GetMacByGetAdaptersInfo函数,通过调用系统的GetAdaptersInfo获取计算机的主网卡的MAC地址。函数首先分配内存来存储适配器信息,然后调用GetAdaptersInfo获取适配器信息。如果内存不足,它会重新分配足够的内存并再次调用该函数。接着,它遍历返回的适配器信息,找到第一个类型为以太网且物理地址长度为6的适配器,然后将其MAC地址以格式化字符串的形式存储在传入的macOUT变量中。最后,释放分配的内存,并返回一个布尔值。
#define _CRT_SECURE_NO_WARNINGS
#define _WIN32_DCOM
#define _CRT_NONSTDC_NO_DEPRECATE
#include <iostream>
#include <winsock2.h>
#include <iphlpapi.h>
#include <string>
#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;
}
第三种封装一个GetMacByNetBIOS函数,其使用NetBIOS API获取指定适配器号(adapterNum)的MAC地址。函数首先通过NCBRESET命令重置指定网卡以便进行查询。接着,使用NCBASTAT命令获取接口卡的状态块,其中包含了适配器的物理地址。如果NetBIOS调用成功,将适配器的MAC地址以格式化字符串的形式存储在传入的macOUT变量中,最后返回一个布尔值。
#include <iostream>
#include <winsock2.h>
#include <iphlpapi.h>
#include <string>
#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地址的更多相关文章
- 获取客户端网卡MAC地址和IP地址实现JS代码
获取客户端网卡MAC地址和IP地址实现JS代码 作者: 字体:[增加 减小] 类型:转载 获取客户端的一些信息,如IP和MAC,以结合身份验证,相信很多人都会这样做吧,我们这里用Javascrip ...
- C# 获取物理网卡Mac地址
// <summary> /// 获取网卡物理地址 /// </summary> /// <returns></returns> public stat ...
- Python 获取 网卡 MAC 地址
/*********************************************************************** * Python 获取 网卡 MAC 地址 * 说明: ...
- 获取CPU序列号、网卡MAC地址、硬盘序列号
<pre name="code" class="csharp"> using System; using System.Collections; u ...
- 工作日记:C#获取操作系统、MAC地址、登录用户、网卡、物理内存信息
/// <summary> /// 操作系统的登录用户名 /// </summary> /// <returns>系统的登录用户名</returns> ...
- 使用WinPcap获取网卡MAC地址
关键字:WinPcap 网卡 MAC地址 作者:txw1958 在WpdPack_4_1_2\WpdPack\Examples-remote\PacketDriver\GetMacAddress\目录 ...
- Java/JSP获得客户端网卡MAC地址的三种方法解析
java/jsp获得客户端(IE)网卡MAC地址的方法大概有三种. 1.通过命令方式,在客户端执行Ipconfig 等等.(java/jsp) 2.通过ActiveX的方法.(jsp) 3.通过向13 ...
- linux/Centos下查看和修改网卡Mac地址(ifconfig命令)
本文转载自http://www.169it.com/article/14360294838474691537.html linux/Centos下查看网卡Mac地址,输入命令: #ifconfig - ...
- Centos下查看和修改网卡Mac地址
linux/Centos下查看网卡Mac地址,输入命令: #ifconfig -a eth0 Link encap:Ethernet HWaddr 00:e4:56:2E:D8:20 00:e4:56 ...
- Java获取本机MAC地址[转]
原文地址:https://www.cnblogs.com/hxsyl/p/3422191.html Java获取本机MAC地址 为什么写这个呢?因为前几天看见网上有采用windows命令获取局域网 ...
随机推荐
- python 正则表达式简单使用
定义: 正则表达式,又称规则表达式,通常被用来检索.替换那些符合某个模式(规则)的文本. 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个&quo ...
- 微软的一些公开课,Python、机器学习、SQL、AI,全部免费
大家好,我是老章,刷X看到一位博主Alif Hossain@alifcoder总结了微软的一些公开课,全部免费,蛮不错的.感兴趣可以学一波,还能领徽章. 1. 机器学习简介 本课程是学习机器学习基础知 ...
- PS 新建作业DUMP DBSQL_DUPLICATE_KEY_ERROR
1.CJ20N新建作业 在CJ20N中新建作业后,保存DUMP,报以下错误 2.相关NOTE 605584 - CN22: update termination when creating activ ...
- Spark SQL 字段血缘在 vivo 互联网的实践
作者:vivo互联网服务器团队-Hao Guangshi 一.背景 字段血缘是在表处理的过程中将字段的处理过程保留下来.为什么会需要字段血缘呢? 有了字段间的血缘关系,便可以知道数据的来源去处,以及字 ...
- 嵌入式Linux必读经典书籍(含下载方式)
最近,在知乎看到一个问题,"嵌入式Linux有哪些好书推荐".我读研期间也喜欢收藏一些书籍,每次看到京东有活动,总是忍不住想买一些书籍回来. 随着时间越来越久,我买的书越来越多,但 ...
- [tslint] Identifier 'loggedIn' is never reassigned; use 'const' instead of 'let'. (prefer-const)
- freeswitch查看所有通道变量
概述 freeswitch 是一款好用的开源软交换平台. 实际应用中,我们经常需要对fs中的通道变量操作,包括设置和获取,set & get. 但是,fs中有众多的内部定义通道变量,也有外部传 ...
- md文件的基本常用编写语法
md简介 .md即markdown文件的基本常用编写语法,是一种快速标记.快速排版语言,现在很多前段项目中的说明文件readme等都是用.md文件编写的,而且很多企业也在在鼓励使用这种编辑方式.下面就 ...
- python进阶(5)--函数
文档目录: 一.函数体二.实参与形参三.返回值四.举例:函数+while循环五.举例:列表/元组/字典传递六.模块与函数的导入 ------------------------------------ ...
- Linux-分区-fdisk-mkfs-mount