C/C++獲取主機(jī)網(wǎng)卡MAC地址的三方法
MAC地址(Media Access Control address),又稱為物理地址或硬件地址,是網(wǎng)絡(luò)適配器(網(wǎng)卡)在制造時(shí)被分配的全球唯一的48位地址。這個(gè)地址是數(shù)據(jù)鏈路層(OSI模型的第二層)的一部分,用于在局域網(wǎng)(LAN)中唯一標(biāo)識(shí)網(wǎng)絡(luò)設(shè)備。獲取網(wǎng)卡地址主要用于網(wǎng)絡(luò)標(biāo)識(shí)和身份驗(yàn)證的目的。MAC地址是一個(gè)唯一的硬件地址,通常由網(wǎng)卡的制造商在制造過程中分配。通過獲取MAC地址可以判斷當(dāng)前主機(jī)的唯一性可以與IP地址綁定并實(shí)現(xiàn)網(wǎng)絡(luò)準(zhǔn)入控制。
在Windows平臺(tái)下獲取MAC地址的方式有很多,獲取MAC地址的常見方式包括使用操作系統(tǒng)提供的網(wǎng)絡(luò)API(如Windows的GetAdaptersAddresses和GetAdaptersInfo),NetBIOS API,系統(tǒng)命令(如ipconfig /all),ARP緩存表查詢,第三方庫(kù)(如WinPcap或Libpcap),以及在編程語言中使用網(wǎng)絡(luò)庫(kù)。
首先第一種獲取方法封裝GetMacByGetAdaptersAddresses函數(shù),該功能的實(shí)現(xiàn)通過調(diào)用系統(tǒng)中的GetAdaptersAddresses獲取計(jì)算機(jī)的MAC地址。
該函數(shù)首先分配內(nèi)存來存儲(chǔ)適配器信息,然后調(diào)用 GetAdaptersAddresses 函數(shù)獲取適配器信息。如果內(nèi)存不足,它會(huì)重新分配足夠的內(nèi)存并再次調(diào)用該函數(shù)。接著,它遍歷返回的適配器信息,找到第一個(gè)物理地址長(zhǎng)度為6的適配器,然后將其MAC地址以格式化字符串的形式存儲(chǔ)在傳入的 macOUT 變量中。最后,釋放分配的內(nèi)存,并返回一個(gè)布爾值。
#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地址的長(zhǎng)度為 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函數(shù),通過調(diào)用系統(tǒng)的GetAdaptersInfo獲取計(jì)算機(jī)的主網(wǎng)卡的MAC地址。函數(shù)首先分配內(nèi)存來存儲(chǔ)適配器信息,然后調(diào)用GetAdaptersInfo獲取適配器信息。如果內(nèi)存不足,它會(huì)重新分配足夠的內(nèi)存并再次調(diào)用該函數(shù)。接著,它遍歷返回的適配器信息,找到第一個(gè)類型為以太網(wǎng)且物理地址長(zhǎng)度為6的適配器,然后將其MAC地址以格式化字符串的形式存儲(chǔ)在傳入的macOUT變量中。最后,釋放分配的內(nèi)存,并返回一個(gè)布爾值。
#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)
{
// 確保是以太網(wǎng)
if (pAdapter->Type != MIB_IF_TYPE_ETHERNET)
continue;
// 確保MAC地址的長(zhǎng)度為 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;
}
第三種封裝一個(gè)GetMacByNetBIOS函數(shù),其使用NetBIOS API獲取指定適配器號(hào)(adapterNum)的MAC地址。函數(shù)首先通過NCBRESET命令重置指定網(wǎng)卡以便進(jìn)行查詢。接著,使用NCBASTAT命令獲取接口卡的狀態(tài)塊,其中包含了適配器的物理地址。如果NetBIOS調(diào)用成功,將適配器的MAC地址以格式化字符串的形式存儲(chǔ)在傳入的macOUT變量中,最后返回一個(gè)布爾值。
#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));
// 重置網(wǎng)卡 以便我們可以查詢
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = adapterNum;
if (Netbios(&Ncb) != NRC_GOODRET)
return false;
// 準(zhǔn)備取得接口卡的狀態(tài)塊
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)
{
// 取得網(wǎng)卡列表
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;
}
三種方式均可以輸出系統(tǒng)的MAC地址,可根據(jù)自己的需求選擇;

以上就是C/C++獲取主機(jī)網(wǎng)卡MAC地址的三方法的詳細(xì)內(nèi)容,更多關(guān)于C/C++ 獲取MAC地址的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux網(wǎng)絡(luò)編程之基于UDP實(shí)現(xiàn)可靠的文件傳輸示例
這篇文章主要介紹了Linux網(wǎng)絡(luò)編程之基于UDP實(shí)現(xiàn)可靠的文件傳輸示例,是很實(shí)用的技巧,需要的朋友可以參考下2014-08-08
一篇文章教你自己動(dòng)手實(shí)現(xiàn)C語言庫(kù)函數(shù)
這篇文章主要介紹了C語言庫(kù)函數(shù)的相關(guān)資料,小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-09-09

