2013-04-29 60 views
5

在我做的那一刻:得到可靠的IPv6地址在Python

def get_inet_ip(): 
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    s.connect(('mysite.com', 80)) 
    return s.getsockname()[0] 

这是基于: Finding local IP addresses using Python's stdlib

然而,这看起来有点可疑。据我所知,它打开一个socket到mysite.com:80,然后返回该套接字的第一个地址,假设它是一个IPv4地址。这似乎有点狡猾......我不认为我们可以保证这是事实。

这是我的第一个问题,它是安全的吗?在启用IPv6的服务器上,IPv6地址是否可以意外返回?

我的第二个问题是,如何以类似的方式获取IPv6地址。我将修改函数以获取可选的ipv6参数。

+0

这不是对IPv4的可靠方法。 – 2013-04-30 15:01:00

+0

是的,我以为没有。请进一步解释。 – 2013-05-07 15:13:09

回答

1

你应该使用功能socket.getaddrinfo()

示例代码来获得IPv6的

def get_ip_6(host,port=80): 
    # discard the (family, socktype, proto, canonname) part of the tuple 
    # and make sure the ips are unique 
    alladdr = list(
     set(
      map(
       lambda x: x[4], 
       socket.getaddrinfo(host,port) 
      ) 
     ) 
    ) 
    ip6 = filter(
     lambda x: ':' in x[0], # means its ip6 
     alladdr 
    ) 
    return ip6 
+0

我会发现最好过滤结果的地址族字段,而不是返回地址的文本重新生成。看到我的答案。 – glglgl 2013-04-29 11:40:56

+0

lambda等会在2.4下工作吗?它必须兼容。 – 2013-04-29 11:46:31

+0

@glglgl是的你是对的,这只是一个快速而肮脏的例子。重点主要是将他重定向到socket.getaddrinfo()文档。 – katharas 2013-05-14 11:03:08

6

问题是,你只是想连接,或做你真正想要的地址?

如果你只是想连接,你可以做

s = socket.create_connection(('mysite.com', 80)) 

,并有建立连接。

但是,如果你有兴趣的地址,你可以去以下方式之一:

def get_ip_6(host, port=0): 
    import socket 
    # search only for the wanted v6 addresses 
    result = socket.getaddrinfo(host, port, socket.AF_INET6) 
    return result # or: 
    return result[0][4][0] # just returns the first answer and only the address 

,或者更接近another, already presented solution

def get_ip_6(host, port=0): 
    # search for all addresses, but take only the v6 ones 
    alladdr = socket.getaddrinfo(host,port) 
    ip6 = filter(
     lambda x: x[0] == socket.AF_INET6, # means its ip6 
     alladdr 
    ) 
    # if you want just the sockaddr 
    # return map(lambda x:x[4],ip6) 
    return list(ip6)[0][4][0] 
+0

是的,我想要IP,它进入一个配置文件。 – 2013-04-29 11:46:10