web-dev-qa-db-de.com

Wie bestimme ich alle meine IP-Adressen, wenn ich mehrere Netzwerkkarten habe?

Auf meinem Computer befinden sich mehrere Netzwerkkarten mit jeweils einer eigenen IP-Adresse.

Wenn ich gethostbyname(gethostname()) aus dem (integrierten) socket-Modul von Python verwende, wird nur eines davon zurückgegeben. Wie bekomme ich die anderen?

30
Wilson F

Verwenden Sie das Modul netifaces . Da die Vernetzung komplex ist, kann die Verwendung von Netifaces etwas kompliziert sein. Hier erfahren Sie jedoch, wie Sie das tun, was Sie möchten:

>>> 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 lesbarer gemacht 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 anstelle von AF_INET. Wenn Sie sich fragen, warum netifaces überall Listen und Wörterbücher verwendet, liegt dies daran, dass ein einzelner Computer mehrere Netzwerkkarten haben kann und jede NIC mehrere Adressen haben kann und jede Adresse ihre eigenen Optionen hat.

43
Harley Holcombe
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
10
Nakilon

Alle Adressen in einer Zeile mit Hilfe des Moduls netifaces:

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

Der Vollständigkeit halber wäre es auch möglich, psutil zu verwenden.

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))

Erläuterung

Die Funktion, die Sie benötigen, ist net_if_addrs . Dh:

import psutil
psutil.net_if_addrs()

Was zu so etwas führt (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 jeder Schnittstelle mehrere Adressen derselben Familie zugeordnet sein können, handelt es sich bei den Diktatwerten um Listen.

Jede snic ist eine namedtuple , die 5 Felder enthält:

  • family: Die Adressfamilie, entweder AF_INET, AF_INET6 oder psutil.AF_LINK, die sich auf eine MAC-Adresse bezieht.
  • address: Die primäre NIC Adresse (immer festgelegt).
  • netmask: die Netzmaskenadresse (kann keine sein).
  • broadcast: Die Broadcast-Adresse (kann "Keine" sein).
  • ptp: steht für "Punkt zu Punkt"; Dies ist die Zieladresse einer Punkt-zu-Punkt-Schnittstelle (in der Regel ein VPN). broadcast und ptp schließen sich gegenseitig aus (möglicherweise keine).
7
pmav99

https://docs.python.org/3.4/library/socket.html#socket.if_nameindex

socket.if_nameindex ()

Gibt eine Liste der Tupel mit Netzwerkschnittstelleninformationen (Index int, Name string) zurück. OSError, wenn der Systemaufruf fehlschlägt.

Verfügbarkeit: Unix.

Neu in Version 3.3.


hat diesen Code erstellt, der unter Python 3.4, UNIX/Linux ausgeführt werden kann

#!/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 __== "__main__":

    print( active_nic_addresses() )
    print( nic_info() )

Druckt etwas wie:

['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]
2
The Demz

Hier finden Sie eine Routine zum Auffinden aller IPv4- und IPv6-Schnittstellen. Wie bereits erwähnt, funktioniert socket.gethostbyname_ex () nicht für IPv6, und in der Python-Dokumentation wird empfohlen, stattdessen socket.getaddressinfo () zu verwenden.

Diese Routine fügt die Callback-IPv4-Schnittstelle (127.0.0.1) hinzu, und wenn es IPv6-Schnittstellen gibt, fügt sie auch die Callback-IPv6-Schnittstelle (:: 1) hinzu. Socket.getaddrinfo () gibt mir auf meinem Rechner eine oder beide von diesen, aber nur, wenn ich keine anderen Schnittstellen zur Verfügung habe.

Für meine Bedürfnisse wollte ich versuchen, einen UDP-Socket an einem bestimmten Port auf jeder meiner verfügbaren Schnittstellen zu öffnen. Aus diesem Grund enthält der Code "port" und "socket.SOCK_DGRAM". Es ist sicher, diese zu ändern, z. wenn Sie keinen Hafen im Sinn 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]
1
DamonJW

Es ist nur Linux, aber es gibt ein sehr einfaches Rezept hier http://code.activestate.com/recipes/439094/

Wahrscheinlich wird ein ähnlicher Code verwendet wie im Paket netifaces , das in einer anderen Antwort erwähnt wurde (aber die aktuelle Version ist hier verlinkt).

Die socket.getaddrinfo () gibt die gebundene IP-Adresse für das Gerät nicht zurück. Wenn Ihre hosts-Datei eine Zeile mit "127.0.1.1 yourhost.example.com yourhost" enthält, was eine übliche Konfiguration ist, gibt getaddrinfo nur 127.0.1.1 zurück.

1
JimB

Dieses Snippet enthält eine Liste aller verfügbaren IPV4-Adressen im System.

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]
1
Sandeep

Du kannst es ziemlich einfach so machen:

import netifaces

for interface in netifaces.interfaces():
    print netifaces.ifaddresses(interface)

Weitere Informationen finden Sie in der Dokumentation zu netifaces .

0
Tlili Marwen

Wie dieser Thread andeutet, gibt es viele Möglichkeiten, das gleiche Ergebnis zu erzielen. Mein Vorschlag besteht darin, den eingebauten Familienfilter in getaddrinfo() zu nutzen und das standardisierte Tupel wie folgt zu analysieren:

from socket import getaddrinfo, AF_INET, gethostname

for ip in getaddrinfo(Host=gethostname(), port=None, family=AF_INET):   
    print(ip[4][0])

Beispielausgabe:

192.168.55.1
192.168.170.234
0
chjortlund

Ich denke, dass die Antwort von @Harley Holcombe funktioniert, aber wenn Sie einige virtuelle Netzwerkkarten ohne IP-Adresse haben, tritt ein Fehler auf. Das ist also, was ich geändert habe:

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 gibt nur dein lan ipv4 zurück

0
yongdi

Sie sollten alle IP-konfigurierten IP-Adressen direkt beziehen, z. durch Ausführen von ifconfig und Parsen der Ausgabe (es ist auch möglich, was ifconfig direkt in Python macht , zu sehen, wie es in C gemacht wird). Wenn Sie Hostnamen möchten, verwenden Sie gethostbyaddr.

0