Por que o gethostbyaddr (gethostname ()) retorna meu ip ipv6?
-
03-07-2019 - |
Pergunta
Estou trabalhando para fazer um aplicativo de servidor simples com o Python e estou tentando fazer com que o IP vincule o soquete de escuta. Um exemplo que eu olhei para usar isso:
HOST = gethostbyaddr(gethostname())
Com um pouco mais de processamento depois disso, ele deve me dar apenas o IP do host como uma string. Isso deve retornar o endereço IPv4. Mas quando eu executo esse código, ele retorna meu endereço IPv6. Por que faz isso e como posso obter meu endereço IPv4?
Se for relevante, estou usando o Windows Vista e o Python 2.5
Solução
Obter seu endereço IP é mais difícil do que você imagina.
Verificar esta resposta Eu dei para a única maneira confiável que encontrei.
Aqui está o que a resposta diz caso você não goste de clicar nas coisas:
Use o netifaces
módulo. Como a rede é complexa, o uso do Netifaces pode ser um pouco complicado, mas aqui está como fazer o que você deseja:
>>> 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
Isso pode ser tornado um pouco mais legível assim:
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 você deseja endereços IPv6, use AF_INET6
ao invés de AF_INET
. Se você está se perguntando por que netifaces
Usa listas e dicionários em todo o lugar, é porque um único computador pode ter várias NICs, e cada NIC pode ter vários endereços, e cada endereço tem seu próprio conjunto de opções.
Outras dicas
O IPv6 está tendo precedência sobre o IPv4, pois é a família mais recente, geralmente é o que você deseja se o seu nome de host estiver associado a várias famílias. Você deveria estar usando getaddrinfo Para resolução independente da família, aqui está um exemplo,
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];
Que em um host configurado de pilha dupla me dá o seguinte,
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()
Considera um endereço IP como um parâmetro, não um nome de host, por isso estou surpreso que esteja funcionando sem jogar uma exceção. Se você quis dizer gethostbyname()
, seus resultados são mais surpreendentes, pois essa função afirma não suportar IPv6. Resposta da Harley Explica como obter corretamente seu endereço IP.