2013-04-29 59 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