Почему gethostbyaddr (gethostname ()) возвращает мой IPv6 IP? - PullRequest
3 голосов
/ 06 января 2009

Я работаю над созданием простого серверного приложения на python и пытаюсь получить IP-адрес, к которому привязан сокет прослушивания. Пример, на который я смотрел, использует это:

HOST = gethostbyaddr(gethostname())

После небольшой обработки я получу только IP-адрес хоста в виде строки. Это должно вернуть адрес IPv4. Но когда я запускаю этот код, он возвращает мой IPv6-адрес. Почему это происходит и как я могу получить свой IPv4-адрес?

Если это уместно, я использую Windows Vista и Python 2.5

Ответы [ 3 ]

11 голосов
/ 06 января 2009

Получить ваш IP-адрес сложнее, чем вы думаете.

Проверьте этот ответ Я дал один надежный способ, который нашел.

Вот что говорит ответ, если вам не нравится нажимать на вещи:

Используйте модуль netifaces. Поскольку сетевое взаимодействие является сложным, использование netifaces может быть немного сложнее, но вот, как сделать то, что вы хотите:

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

Это можно сделать немного более читабельным, например:

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

Если вы хотите IPv6-адреса, используйте AF_INET6 вместо AF_INET. Если вам интересно, почему netifaces использует списки и словари повсеместно, то это потому, что на одном компьютере может быть несколько сетевых карт, и у каждой сетевой карты может быть несколько адресов, и у каждого адреса есть свой собственный набор параметров.

5 голосов
/ 06 февраля 2010

IPv6 имеет приоритет над IPv4, так как это более новое семейство, обычно это то, что вы хотите, если ваше имя хоста связано с несколькими семействами. Вы должны использовать getaddrinfo для независимого семейного разрешения, вот пример,

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];

Который на хосте с двумя стеками дает мне следующее:

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)
0 голосов
/ 06 января 2009

gethostbyaddr() принимает в качестве параметра IP-адрес, а не имя хоста, поэтому я удивлен, что он работает вообще без исключения. Если вместо этого вы имели в виду gethostbyname(), то ваши результаты более удивительны, поскольку эта функция утверждает, что не поддерживает IPv6. Ответ Харли объясняет, как правильно получить ваш IP-адрес.

...