Wie finde ich heraus, alle meine IP-Adressen, wenn ich mehrere Netzwerkkarten?
-
06-07-2019 - |
Frage
Ich habe von mehreren Netzwerk-Interface-Karten auf meinem computer, jeder mit seiner eigenen IP-Adresse.
Wenn ich benutze gethostbyname(gethostname())
von Python (built-in) socket
Modul, es wird nur einer von Ihnen.Wie bekomme ich die anderen?
Lösung
Mit dem netifaces
Modul. Da Vernetzung komplexer, netifaces verwendet, kann ein wenig schwierig sein, aber hier ist, wie zu tun, was Sie wollen:
>>> 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
Dies kann ein wenig besser lesbar wie folgt vorgenommen werden:
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
Wenn Sie IPv6-Adressen möchten, verwenden Sie AF_INET6
statt AF_INET
. Wenn Sie sich fragen, warum netifaces
Listen und Wörterbücher verwenden alle über den Platz, es ist, weil ein einzelner Computer mehr Netzwerkkarten haben kann, und jeder NIC kann mehrere Adressen hat, und jede Adresse hat seine eigene Reihe von Optionen.
Andere Tipps
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
Alle Adressen in einer Zeile mit Hilfe des netifaces
Modul:
[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]
Nur der Vollständigkeit halber, eine andere Möglichkeit wäre die Verwendung von 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))
Erklärung
Die Funktion, die Sie brauchen, ist net_if_addrs
.I. e.:
import psutil
psutil.net_if_addrs()
Die Ergebnisse in so etwas wie dieser (Python 3):
{'br-ae4880aa80cf': [snic(family=<AddressFamily.AF_INET: 2>, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'docker0': [snic(family=<AddressFamily.AF_INET: 2>, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'eno1': [snic(family=<AddressFamily.AF_PACKET: 17>, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
'wlp2s0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, 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)]}
Hinweis:Da kann man mehr als eine Adresse, die der gleichen Familie, die jeder Schnittstelle, die dict-Werte-Listen.
Jeder snic
ist ein namedtuple
die enthält 5 Felder:
family
:die Adressfamilie AF_INET, AF_INET6 oder psutil.AF_LINK, die sich auf eine MAC-Adresse.address
:die primäre NIC-Adresse (immer setzen).netmask
:die netmask-Adresse (vielleicht Keine).broadcast
:die broadcast-Adresse (vielleicht Keine).ptp
:steht für "Punkt zu Punkt";es ist die Ziel-Adresse auf einem Punkt-zu-Punkt-Schnittstelle (in der Regel ein VPN).broadcast-und ptp schließen sich gegenseitig aus (vielleicht Keine).
https://docs.python.org/3.4/library/ socket.html # socket.if_nameindex
socket.if_nameindex ()
Gibt eine Liste von Netzwerkschnittstelleninformationen (Index int, name string) Tupel. OSError wenn der Systemaufruf fehlschlägt.
Verfügbarkeit:. Unix
Neu in der Version 3.3.
Mit diesem Code gemacht, die auf Python 3.4, UNIX / Linux
fahrbare ist#!/env/python3.4
import socket
import fcntl
import struct
def active_nic_addresses():
"""
Return a list of IPv4 addresses that are active on the computer.
"""
addresses = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]
return addresses
def get_ip_address( NICname ):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', NICname[:15].encode("UTF-8"))
)[20:24])
def nic_info():
"""
Return a list with tuples containing NIC and IPv4
"""
nic = []
for ix in socket.if_nameindex():
name = ix[1]
ip = get_ip_address( name )
nic.append( (name, ip) )
return nic
if __name__ == "__main__":
print( active_nic_addresses() )
print( nic_info() )
Wird so etwas wie Druck:
['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]
Es ist nur Linux, aber es ist ein sehr einfaches Rezept hier http://code.activestate.com / Rezepte / 439094 /
Es nutzt wahrscheinlich einen ähnlichen Code zum netifaces Paket in einer anderen Antwort erwähnt (aber Strom Version verknüpft hier)
Die socket.getaddrinfo () kehrt nicht tatsächlich die gebundene IP-Adresse für das Gerät. Wenn Ihre Hosts-Datei enthält eine Zeile mit „127.0.1.1 yourhost.example.com IhrHost“, die eine gemeinsame Konfiguration ist, Getaddrinfo nur 127.0.1.1 zurückkehren wird.
Hier ist eine Routine für die Suche nach all IPv4- und IPv6-Schnittstellen. Als vorher bereits erwähnt, socket.gethostbyname_ex () funktioniert nicht für IPv6 und die Python-Dokumentation empfiehlt eine socket.getaddressinfo () statt.
Diese Routine fügt die Callback-IPv4-Schnittstelle (127.0.0.1), und wenn es keine IPv6-Schnittstellen ist dann auch den Rückruf IPv6-Schnittstelle ergänzt (:: 1). Auf meinem Rechner socket.getaddrinfo () gibt mir eine oder beide von diesen aber nur, wenn ich keine anderen Schnittstellen zur Verfügung haben.
Für meine Bedürfnisse, ich wollte auf jeden meiner verfügbaren Schnittstellen einen UDP-Socket auf einem bestimmten Port zu öffnen, um zu versuchen, weshalb der Code „Port“ und socket.SOCK_DGRAM darin. Es ist sicher, diejenigen zu ändern, z.B. wenn Sie nicht über einen Hafen im Sinne haben.
addrinfo_ipv4 = socket.getaddrinfo(hostname,port,socket.AF_INET,socket.SOCK_DGRAM)
addrinfo_ipv6 = []
try:
addrinfo_ipv6 = socket.getaddrinfo(hostname,port,socket.AF_INET6,socket.SOCK_DGRAM)
except socket.gaierror:
pass
addrinfo = [(f,t,a) for f,t,p,cn,a in addrinfo_ipv4+addrinfo_ipv6]
addrinfo_local = [(socket.AF_INET,socket.SOCK_DGRAM,('127.0.0.1',port))]
if addrinfo_ipv6:
addrinfo_local.append( (socket.AF_INET6,socket.SOCK_DGRAM,('::1',port)) )
[addrinfo.append(ai) for ai in addrinfo_local if ai not in addrinfo]
Dieser Code-Schnipsel zeigt eine Liste aller verfügbaren IPv4-Adressen im System geben.
import itertools
from netifaces import interfaces, ifaddresses, AF_INET
links = filter(None, (ifaddresses(x).get(AF_INET) for x in interfaces()))
links = itertools.chain(*links)
ip_addresses = [x['addr'] for x in links]
Sie sollten alle IP konfigurierten IP-Adressen direkt erhalten, z.B. von ifconfig laufen und dessen Ausgang das Parsen (es ist auch möglich, zu tun, was ifconfig direkt in Python tut zu sehen, wie es in C erfolgt). Wenn Sie Host-Namen möchten, verwenden gethostbyaddr.
Sie können es ziemlich leicht wie folgt aus:
import netifaces
for interface in netifaces.interfaces():
print netifaces.ifaddresses(interface)
Für weitere Informationen können Sie die netifaces Dokumentation nachschlagen.
ich glaube, @Harley Holcombe Antwort praktikabel ist, aber wenn Sie einige virtuelle NICs ohne ip haben es Fehler. so ist dies i geändert:
def get_lan_ip():
for interface in interfaces():
try:
for link in ifaddresses(interface)[AF_INET]:
if str(link['addr']).startswith("172."):
return str(link['addr'])
except:
pass
Dies wird nur zurückkehren Ihre lan ipv4
Da dieser Thread gibt, gibt es viele Möglichkeiten, um das gleiche Ergebnis acchive, meine vorgeschlagene Art und Weise ist die Bildung in der Familie Filter in getaddrinfo()
zu nutzen und das standardisierte Tupel analysiert wie folgt:
from socket import getaddrinfo, AF_INET, gethostname
for ip in getaddrinfo(host=gethostname(), port=None, family=AF_INET):
print(ip[4][0])
Beispiel Ausgabe:
192.168.55.1
192.168.170.234