获取MAC地址

时间:2020-03-06 14:59:32  来源:igfitidea点击:

我需要一种在运行时确定计算机的MAC地址的跨平台方法。对于Windows,可以使用" wmi"模块,在Linux下,我能找到的唯一方法是运行ifconfig并在其输出中运行一个正则表达式。我不喜欢使用只能在一个OS上运行的程序包,并且更不用说容易出错的语法解析另一个程序的输出。

有谁知道跨平台方法(Windows和Linux)方法来获取MAC地址?如果没有,还有谁比我上面列出的方法更优雅?

解决方案

netifaces是一个很好的模块,可用于获取mac地址(和其他地址)。它是跨平台的,比使用套接字或者uuid更有意义。

>>> import netifaces
>>> netifaces.interfaces()
['lo', 'eth0', 'tun2']

>>> netifaces.ifaddresses('eth0')[netifaces.AF_LINK]
[{'addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]
  • pypi位置
  • netifaces的良好入门

我不知道统一的方式,但是我们可能会发现以下有用的东西:

http://www.codeguru.com/Cpp/I-N/network/networkinformation/article.php/c5451

在这种情况下,我要做的就是将它们包装成一个函数,并根据操作系统运行适当的命令,根据需要进行解析,并仅返回所需格式的MAC地址。当然,除了我们只需要执行一次,并且与主代码相比,它看起来更干净以外,其他所有内容都是一样的。

Python 2.5包含一个uuid实现(至少在一个版本中),该实现需要mac地址。我们可以轻松地将mac查找功能导入我们自己的代码中:

from uuid import getnode as get_mac
mac = get_mac()

返回值是作为48位整数的mac地址。

对于Linux,我们可以使用SIOCGIFHWADDR ioctl检索MAC地址。

struct ifreq    ifr;
uint8_t         macaddr[6];

if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
    return -1;

strcpy(ifr.ifr_name, "eth0");

if (ioctl(s, SIOCGIFHWADDR, (void *)&ifr) == 0) {
    if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
        memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
        return 0;
... etc ...

我们已将问题标记为" python"。我不知道要获取此信息的现有Python模块。我们可以使用ctypes直接调用ioctl。

请注意,我们可以使用条件导入在python中构建自己的跨平台库。例如

import platform
if platform.system() == 'Linux':
  import LinuxMac
  mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
  # etc

这将允许我们使用os.system调用或者特定于平台的库。

我们应该注意的另一件事是,uuid.getnode()可以通过返回随机的48位数字来伪造MAC地址,这可能不是我们所期望的。同样,也没有明显的迹象表明MAC地址已被伪造,但是我们可以通过两次调用getnode()并查看结果是否变化来检测到它。如果两个调用都返回相同的值,则说明我们具有MAC地址,否则得到的是伪造的地址。

>>> print uuid.getnode.__doc__
Get the hardware address as a 48-bit positive integer.

    The first time this runs, it may launch a separate program, which could
    be quite slow.  If all attempts to obtain the hardware address fail, we
    choose a random 48-bit number with its eighth bit set to 1 as recommended
    in RFC 4122.