为什么gethostbyaddr(gethostname())返回我的IPv6 IP?

时间:2009-01-06 04:01:41

标签: python sockets ip-address ipv6 ipv4

我正在使用python创建一个简单的服务器应用程序,我正在尝试将IP绑定到侦听套接字。我看过的一个例子使用了这个:

HOST = gethostbyaddr(gethostname())

在此之后稍微处理一下,它应该只给出主机IP作为字符串。这应该返回IPv4地址。但是当我运行此代码时,它会返回我的IPv6地址。为什么这样做以及如何获取我的IPv4地址?

如果相关,我使用的是windows vista和python 2.5

3 个答案:

答案 0 :(得分:11)

获取您的IP地址比您想象的要难。

检查this answer我给出了一个可靠的方法。

以下是您不喜欢点击内容的答案:

使用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在整个地方使用列表和词典,那是因为一台计算机可以有多个NIC,每个NIC可以有多个地址,每个地址都有自己的一组选项。

答案 1 :(得分:5)

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)

答案 2 :(得分:0)

gethostbyaddr()将IP地址作为参数,而不是主机名,所以我很惊讶它在没有抛出异常的情况下工作。如果您的意思是gethostbyname(),那么您的结果会更令人惊讶,因为该功能声称不支持IPv6。 Harley's answer说明了如何正确获取您的IP地址。