当前位置:  开发笔记 > 编程语言 > 正文

当我有多个NIC时,如何确定所有IP地址?

如何解决《当我有多个NIC时,如何确定所有IP地址?》经验,为你挑选了4个好方法。

我的计算机上有多个网络接口卡,每个都有自己的IP地址.

当我使用gethostbyname(gethostname())Python的(内置)socket模块时,它只返回其中一个.我如何得到其他人?



1> Harley Holco..:

使用该netifaces模块.因为网络很复杂,使用netifaces可能有点棘手,但这里是如何做你想要的:

>>> import netifaces
>>> netifaces.interfaces()
['lo', 'eth0']
>>> netifaces.ifaddresses('eth0')
{17: [{'broadcast': 'ff:ff:ff:ff:ff:ff', 'addr': '00:11:2f:32:63:45'}], 2: [{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}], 10: [{'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::211:2fff:fe32:6345%eth0'}]}
>>> for interface in netifaces.interfaces():
...   print netifaces.ifaddresses(interface)[netifaces.AF_INET]
...
[{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]
[{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}]
>>> for interface in netifaces.interfaces():
...   for link in netifaces.ifaddresses(interface)[netifaces.AF_INET]:
...     print link['addr']
...
127.0.0.1
10.0.0.2

这可以像这样更具可读性:

from netifaces import interfaces, ifaddresses, AF_INET

def ip4_addresses():
    ip_list = []
    for interface in interfaces():
        for link in ifaddresses(interface)[AF_INET]:
            ip_list.append(link['addr'])
    return ip_list

如果您需要IPv6地址,请使用AF_INET6而不是AF_INET.如果您想知道为什么netifaces在整个地方使用列表和词典,那是因为一台计算机可以有多个NIC,每个NIC可以有多个地址,每个地址都有自己的一组选项.


我已将其更改为`for ifaddresses(interface).get(AF_INET,())`中的链接.我也忽略了一些像'lo0'这样的接口.
@HarleyHolcombe - 如果NIC没有IPv4地址,并且应该对AF_INET和'addr'都使用dict.get(key)形式,则ip4_addresses()函数会抛出KeyError.我用修复程序提交了你的答案的编辑,但我的编辑被拒绝了(???).

2> Nakilon..:
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]


这只列出了连接到外部世界的接口的地址,而不是所有接口.

3> 小智..:

netifaces模块的帮助下,所有地址都在一行中:

[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]



4> pmav99..:

仅仅为了完整性,另一种选择是使用psutil.

tldr;

import socket
import psutil

def get_ip_addresses(family):
    for interface, snics in psutil.net_if_addrs().items():
        for snic in snics:
            if snic.family == family:
                yield (interface, snic.address)

ipv4s = list(get_ip_addresses(socket.AF_INET))
ipv6s = list(get_ip_addresses(socket.AF_INET6))

说明

你需要的功能是net_if_addrs.即:

import psutil
psutil.net_if_addrs()

结果是这样的(Python 3):

{'br-ae4880aa80cf': [snic(family=, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
                     snic(family=, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'docker0': [snic(family=, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
             snic(family=, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'eno1': [snic(family=, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'lo': [snic(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
        snic(family=, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
 'wlp2s0': [snic(family=, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
            snic(family=, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

(Python 2):

{'br-ae4880aa80cf': [snic(family=2, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
                     snic(family=17, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'docker0': [snic(family=2, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
             snic(family=17, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'eno1': [snic(family=17, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'lo': [snic(family=2, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
        snic(family=17, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
 'wlp2s0': [snic(family=2, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
            snic(family=17, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

注意:由于每个接口可以有多个相同系列的地址,因此dict值是列表.

每个snicnamedtuple包括5个字段:

family:地址系列,AF_INET,AF_INET6或psutil.AF_LINK,它指的是MAC地址.

address:主NIC地址(始终设置).

netmask:网络掩码地址(可以是None).

broadcast:广播地址(可能是None).

ptp:代表"点对点"; 它是点对点接口(通常是VPN)上的目标地址.broadcast和ptp是互斥的(可以是None).

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有