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

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top