【问题标题】:Why does gethostbyaddr(gethostname()) return my IPv6 IP?为什么 gethostbyaddr(gethostname()) 返回我的 IPv6 IP?
【发布时间】:2010-09-29 17:56:24
【问题描述】:

我正在使用 python 制作一个简单的服务器应用程序,并且我正在尝试获取 IP 以将侦听套接字绑定到。我看过的一个例子是这样使用的:

HOST = gethostbyaddr(gethostname())

在此之后再进行一些处理,它应该只给我主机 IP 作为字符串。这应该返回 IPv4 地址。但是当我运行这段代码时,它会返回我的 IPv6 地址。为什么会这样?我怎样才能获得我的 IPv4 地址?

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

【问题讨论】:

    标签: python sockets ip-address ipv6 ipv4


    【解决方案1】:

    获取您的 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 可以有多个地址,每个地址都有自己的一组选项。

    【讨论】:

      【解决方案2】:

      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)
      

      【讨论】:

        【解决方案3】:

        gethostbyaddr() 将 IP 地址作为参数,而不是主机名,所以我很惊讶它完全可以正常工作而不会引发异常。相反,如果您的意思是gethostbyname(),那么您的结果会更令人惊讶,因为该函数声称不支持 IPv6。 Harley's answer 解释了如何正确获取您的 IP 地址。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-30
          • 1970-01-01
          • 2016-03-29
          相关资源
          最近更新 更多