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-00if (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-00if (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);// 取得MACfor (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地址,可根据自己的需求选择;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/193240.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STL的介绍

STL 是 C 标准模板库&#xff08;Standard Template Library&#xff09;的缩写&#xff0c;是 C 标准库中的一个重要组成部分。STL 提供了一组通用的模板类和函数&#xff0c;用于实现常用的数据结构和算法&#xff0c;如向量&#xff08;vector&#xff09;、链表&#xff08…

Alien Skin Exposure2024免费版图片颜色滤镜插件

Alien Skin Exposure一款非常专业的图片后期处理软件&#xff0c;内含500多种照片滤镜。是一款图片后期处理功能非常强大的软件。这款软件可以对图片的后期效果做很好的处理。 打开Alien Skin Exposure软件&#xff0c;会显示下面这个界面&#xff0c;如图1. ExposureX8win-安…

vue下载xlsx表格

vue下载xlsx表格 // 导入依赖库 import XLSX from xlsx; import FileSaver from file-saver; methods:{btn(){let date new Date()let Y date.getFullYear() -let M (date.getMonth() 1 < 10 ? 0 (date.getMonth() 1) : date.getMonth() 1) -let D (date.getDat…

vue引入前端工程内的图片

一、public目录下的图片 public目录下的图片引入方式&#xff1a; <!--/images/图片名称&#xff0c;这种属于绝对路径&#xff0c;/指向public目录 --> <img src"/images/image.png"> 二、src目录下的图片 先在vue.config.js进行配置&#xff0c;并指…

周年纪念篇

一周年纪念&#xff01; 凌晨逛手机版csdn时才突然发现已经错过一周年了&#xff0c;但我当闰年来纪念一下不过分吧hhh 浅浅的整些怀念的东西吧&#xff01; 这是人生第一段代码&#xff1a;不是hello world写不起&#xff0c;而是纯爱单推人更有性价比。 有这段代码在&#x…

移动端表格分页uni-app

使用uni-app提供的uni-table表格 网址&#xff1a;https://uniapp.dcloud.net.cn/component/uniui/uni-table.html#%E4%BB%8B%E7%BB%8D <uni-table ref"table" :loading"loading" border stripe type"selection" emptyText"暂无更多数据…

英飞凌(Infineon)平台嵌入式开发基础

本篇文章介绍了基于英飞凌平台进行嵌入式开发的一些基础知识&#xff0c;首先介绍了涉及芯片的信息和常见的开发环境&#xff0c;把生硬的主体名称先分类并抛出来&#xff1b;然后着重介绍了英飞凌官网提供的开发资源&#xff0c;包括不限于开发环境&#xff0c;代码示例&#…

Mol-Instructions:大模型赋能,药物研发新视野

论文标题&#xff1a;Mol-Instructions: A Large-Scale Biomolecular Instruction Dataset for Large Language Models 论文链接&#xff1a; https://arxiv.org/pdf/2306.08018.pdf Github链接&#xff1a; https://github.com/zjunlp/Mol-Instructions 模型下载&#xf…

linux如何使用Xshell远程连接

简介&#xff1a;本文的一切条件基于redhat的linux操作系统。 1、创建虚拟机&#xff1a; 如有需要&#xff0c;请转至【linux基础】在VMware上安装RHEL9详细教程_融社的博客-CSDN博客 &#xff08;如若侵权&#xff0c;该篇立删&#xff09; 2、使用命令查看网段信息 打…

【漏洞复现】浙大恩特CRM文件上传0day

漏洞描述 浙大恩特客户资源管理系统任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用…

Java Swing垃圾分类器

内容要求 1) 本次程序设计是专门针对 Java 课程的,要求使用 Java 语言进行具有一定代码量的程序开发。程序的设计要结合一定的算法&#xff0c;在进行代码编写前要能够设计好自己的算法。 本次程序设计涉及到 Java 的基本语法&#xff0c;即课堂上所介绍的变量、条件语句、循…

【django+vue】项目搭建、解决跨域访问

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 【djangovue】项目搭建、解决跨域访问 djangovue介绍vue环境准备vue框架搭建1.创建vue项目2.配置vue项目3.进入项目目录4.运行项目5.项目文件讲解6.vue的扩展库或者插件 django环境准备django框架搭建1.使用conda…