Reliably get IPV6 address in Python

Currently:

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

This was based on: Finding local IP addresses using stdlib Python

However, this looks a bit dubious. As far as I can tell, it opens a socket for mysite.com:80, and then returns the first address for that socket, considering it an IPv4 address. It seems a little dodgy ... I don't think we can ever guarantee that it is.

This is my first question, is it safe? On a server that supports IPv6, can an IPv6 address ever return unexpectedly?

My second question is: how do I get an IPv6 address in a similar way. I am going to change the function to take the optional ipv6 parameter.

+5
source share
2 answers

, ?

,

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

, , :

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]
+6

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

All Articles