获取系统网络MAC地址的三种方法
2008-12-06 22:39
417 查看
目的 | ||||||||||||
这篇文章的目的是给出一些得知你MAC地址的简单方法。我会解释这些代码是如何工作的,并给出一些简单的例子来阐述。我假设你已经掌握了下面的概念: Borland C++Builder 简单的网络概念 一些 Win32 API | ||||||||||||
方法一 - 用Netbios API | ||||||||||||
这个方法是通过微软的Netbios API来得到你机器的MAC地址。这些API是一组提供比所谓的Winsock更底层的网络支持的命令。通过Netbios来得到地质这种方法的确定就是你必须安装了Netbios(如果你在一个Windows网络上并使用了文件共享,就没有这个问题)。另外,这个方法快速又准确。 Netbios API只包含了一个简称为Netbios的函数。这个函数通过一个网络控制块结构作为参数,来告诉函数需要做什么。这个结构的定义如下:
枚举所有的网络适配器 重启每一个适配器以便得到它的正确信息 查询该适配器来得到MAC地址并将地址填入标准的colon-separated格式(指用冒号分割的格式) 下面的代码简单是这些概念的简单示例。有关Netbios函数的更多信息请参考微软帮助文件或MSDN。
| ||||||||||||
方法二 - COM GUID API | ||||||||||||
这个方法用COM API来创建一个GUID(globably unique identifier,全局唯一标识符)并且从那里得到MAC地址。GUID是用来一般地标识系统中的COM组件或者其他对象。他们通过MAC地址(再加上其他东西)计算出来的,并且在表面上看还将地址保留在GUID中。我说表面上的原因是这还不确定。我提供这个方法作主要是作为一个不要做什么的例子。按这种方法你有可能最终得到MAC地址,但也可能你最后会得到一些随机的十六进制数。 这个方法非常的简单,并不需要太多的解释。我们通过CoCreateGuid创建一个GUID并将最后的6字节存入一个字符串。这应该就是MAC地址,但就像我说的一样,并没有方法可以保证。
|
得到适配器列表
查询每一个适配器的类型和MAC地址
将实际是NIC的适配器保存
我个人并不太熟悉SNMP,但一如我之前所讲,代码非常的清晰。参考以下的地址可获得更多信息:
SNMP Functions
SNMP Variable Types and Request PDU Types
SNMP Structures
snmp.cpp |
#include <snmp.h> #include <conio.h> #include <stdio.h> typedef bool(WINAPI * pSnmpExtensionInit) ( IN DWORD dwTimeZeroReference, OUT HANDLE * hPollForTrapEvent, OUT AsnObjectIdentifier * supportedView); typedef bool(WINAPI * pSnmpExtensionTrap) ( OUT AsnObjectIdentifier * enterprise, OUT AsnInteger * genericTrap, OUT AsnInteger * specificTrap, OUT AsnTimeticks * timeStamp, OUT RFC1157VarBindList * variableBindings); typedef bool(WINAPI * pSnmpExtensionQuery) ( IN BYTE requestType, IN OUT RFC1157VarBindList * variableBindings, OUT AsnInteger * errorStatus, OUT AsnInteger * errorIndex); typedef bool(WINAPI * pSnmpExtensionInitEx) ( OUT AsnObjectIdentifier * supportedView); void main() { HINSTANCE m_hInst; pSnmpExtensionInit m_Init; pSnmpExtensionInitEx m_InitEx; pSnmpExtensionQuery m_Query; pSnmpExtensionTrap m_Trap; HANDLE PollForTrapEvent; AsnObjectIdentifier SupportedView; UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}; UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1}; UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6}; AsnObjectIdentifier MIB_ifMACEntAddr = { sizeof(OID_ipMACEntAddr) sizeof(UINT), OID_ipMACEntAddr }; AsnObjectIdentifier MIB_ifEntryType = {sizeof(OID_ifEntryType) sizeof(UINT), OID_ifEntryType}; AsnObjectIdentifier MIB_ifEntryNum = {sizeof(OID_ifEntryNum) sizeof(UINT), OID_ifEntryNum}; RFC1157VarBindList varBindList; RFC1157VarBind varBind[2]; AsnInteger errorStatus; AsnInteger errorIndex; AsnObjectIdentifier MIB_NULL = {0, 0}; int ret; int dtmp; int i = 0, j = 0; bool found = false; char TempEthernet[13]; m_Init = NULL; m_InitEx = NULL; m_Query = NULL; m_Trap = NULL; /* 加载SNMP动态链接库并得到所需函数的地址 */ m_hInst = LoadLibrary("inetmib1.dll"); if (m_hInst < (HINSTANCE) HINSTANCE_ERROR) { m_hInst = NULL; return; } m_Init = (pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit"); m_InitEx = (pSnmpExtensionInitEx) GetProcAddress(m_hInst, "SnmpExtensionInitEx"); m_Query = (pSnmpExtensionQuery) GetProcAddress(m_hInst, "SnmpExtensionQuery"); m_Trap = (pSnmpExtensionTrap) GetProcAddress(m_hInst, "SnmpExtensionTrap"); m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView); /* 初始化m_Query将传回的变量列表 */ varBindList.list = varBind; varBind[0].name = MIB_NULL; varBind[1].name = MIB_NULL; /* 拷贝OID以在接口表中查找到表目(适配器)数量 */ varBindList.len = 1; /* 仅处理一条记录 */ SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum); ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex); printf("# of adapters in this system : %in", varBind[0].value.asnValue.number); varBindList.len = 2; /* 拷贝入OID接口类型ifType */ SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType); /* 拷贝入OID地址ifPhysAddress */ SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr); do { /* 提交查询。应答将被填入varBindList。 Submit the query. Responses will be loaded into varBindList. 我们可以认为后续调用的执行次数与系统所报告的适配器数目相同。 */ ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex); if (!ret) ret = 1; else /* 确认已经返回正确的类型 */ ret = SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength); if (!ret) { j++; dtmp = varBind[0].value.asnValue.number; printf("Interface #%i type : %in", j, dtmp); /* 类型6标识以太网接口 */ if (dtmp == 6) { /* 这里确认我们有了一个地址 */ ret = SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr, MIB_ifMACEntAddr.idLength); if ((!ret) && (varBind[1].value.asnValue.address.stream != NULL)) { if((varBind[1].value.asnValue.address.stream[0] == 0x44) && (varBind[1].value.asnValue.address.stream[1] == 0x45) && (varBind[1].value.asnValue.address.stream[2] == 0x53) && (varBind[1].value.asnValue.address.stream[3] == 0x54) && (varBind[1].value.asnValue.address.stream[4] == 0x00)) { /* 忽略所有的拨号网络适配器 */ printf("Interface #%i is a DUN adaptern", j); continue; } if ((varBind[1].value.asnValue.address.stream[0] == 0x00) && (varBind[1].value.asnValue.address.stream[1] == 0x00) && (varBind[1].value.asnValue.address.stream[2] == 0x00) && (varBind[1].value.asnValue.address.stream[3] == 0x00) && (varBind[1].value.asnValue.address.stream[4] == 0x00) && (varBind[1].value.asnValue.address.stream[5] == 0x00)) { /* 忽略其他网络接口返回的NULL地址 */ printf("Interface #%i is a NULL addressn", j); continue; } sprintf(TempEthernet, "%02x%02x%02x%02x%02x%02x", varBind[1].value.asnValue.address.stream[0], varBind[1].value.asnValue.address.stream[1], varBind[1].value.asnValue.address.stream[2], varBind[1].value.asnValue.address.stream[3], varBind[1].value.asnValue.address.stream[4], varBind[1].value.asnValue.address.stream[5]); printf("MAC Address of interface #%i: %sn", j, TempEthernet);} } } } while (!ret); /* 遇到错误时停止。当我们遍历完所有需被测试的接口后会产生一个错误。 */ getch(); FreeLibrary(m_hInst); /* 释放邦定 */ SNMP_FreeVarBind(&varBind[0]); SNMP_FreeVarBind(&varBind[1]); } |
相关文章推荐
- 获取系统网络MAC地址的三种方法
- [译]获取系统网络MAC地址的三种方法
- windows及Linux系统下获取IP及MAC地址的方法
- DOS命令下的三种获取远程主机MAC地址的方法
- 取得系统中网卡MAC地址的三种方法
- 取得系统中网卡MAC地址的三种方法
- 取得系统中网卡MAC地址的三种方法vc++技
- DOS命令下获取远程主机MAC地址的三种方法
- 获取MAC地址最有效方法作为软件加密时用到在不同系统平台下
- Android6.0系统MAC地址获取的方法
- 取得系统中网卡MAC地址的三种方法
- DOS命令下的三种获取远程主机MAC地址的方法
- DOS命令下获取远程主机MAC地址的三种方法
- windows下获取MAC地址的三种方法
- DOS命令下获取远程主机MAC地址的三种方法
- 取得系统中网卡MAC地址的三种方法
- 取得系统中网卡MAC地址的三种方法
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
- Delphi代码获取网卡物理地址三种方法
- 系统自动设置网络参数即自动获取IP的方法