Perché gethostbyaddr (gethostname ()) restituisce il mio IP IPv6?
-
03-07-2019 - |
Domanda
Sto lavorando per creare una semplice applicazione server con Python e sto cercando di ottenere l'IP a cui collegare il socket di ascolto. Un esempio che ho visto usa questo:
HOST = gethostbyaddr(gethostname())
Con un po 'più di elaborazione dopo questo, dovrebbe darmi solo l'IP host come una stringa. Questo dovrebbe restituire l'indirizzo IPv4. Ma quando eseguo questo codice, restituisce il mio indirizzo IPv6. Perché lo fa e come posso ottenere il mio indirizzo IPv4?
Se è pertinente, sto usando Windows Vista e Python 2.5
Soluzione
Ottenere il tuo indirizzo IP è più difficile di quanto pensi.
Controlla questa risposta ho dato per l'unico modo affidabile che ho trovato.
Ecco cosa dice la risposta nel caso in cui non ti piace fare clic sulle cose:
Utilizza il modulo netifaces
. Poiché la rete è complessa, l'utilizzo di netifaces può essere un po 'complicato, ma ecco come fare quello che vuoi:
>>> 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
Questo può essere reso un po 'più leggibile in questo modo:
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
Se desideri indirizzi IPv6, usa AF_INET6
invece di AF_INET
. Se ti stai chiedendo perché netifaces
utilizza elenchi e dizionari ovunque, è perché un singolo computer può avere più schede di rete e ogni scheda di rete può avere più indirizzi e ogni indirizzo ha il proprio set di opzioni .
Altri suggerimenti
IPv6 ha la precedenza su IPv4 poiché è la famiglia più recente, in genere è ciò che si desidera se il nome host è associato a più famiglie. Dovresti utilizzare getaddrinfo per una risoluzione indipendente dalla famiglia, ecco un esempio,
import sys, socket;
host = socket.gethostname();
result = socket.getaddrinfo(host, None);
print "family:%i socktype:%i proto:%i canonname:%s sockaddr:%s"%result[0];
result = socket.getaddrinfo(host, None, socket.AF_INET);
print "family:%i socktype:%i proto:%i canonname:%s sockaddr:%s"%result[0];
result = socket.getaddrinfo(host, None, socket.AF_INET6);
print "family:%i socktype:%i proto:%i canonname:%s sockaddr:%s"%result[0];
Che su un host configurato dual-stack mi dà quanto segue,
family:10 socktype:1 proto:6 canonname: sockaddr:('2002:dce8:d28e::31', 0, 0, 0)
family:2 socktype:1 proto:6 canonname: sockaddr:('10.6.28.31', 0)
family:10 socktype:1 proto:6 canonname: sockaddr:('2002:dce8:d28e::31', 0, 0, 0)
gethostbyaddr ()
accetta un indirizzo IP come parametro, non un nome host, quindi sono sorpreso che funzioni affatto senza generare un'eccezione. Se invece intendevi gethostbyname ()
, quindi i tuoi risultati sono più sorprendenti, dal momento che quella funzione afferma di non supportare IPv6. La risposta di Harley spiega come ottenere correttamente il tuo indirizzo IP.