views:

1027

answers:

3

I'm working on making a simple server application with python, and I'm trying to get the IP to bind the listening socket to. An example I looked at uses this:

HOST = gethostbyaddr(gethostname())

With a little more processing after this, it should give me just the host IP as a string. This should return the IPv4 address. But when I run this code, it returns my IPv6 address. Why does it do this and how can I get my IPv4 address?

If its relevant, I'm using windows vista and python 2.5

+8  A: 

Getting your IP address is harder than you might think.

Check this answer I gave for the one reliable way I've found.

Here's what the answer says in case you don't like clicking on things:

Use the netifaces module. Because networking is complex, using netifaces can be a little tricky, but here's how to do what you want:

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

This can be made a little more readable like this:

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

If you want IPv6 addresses, use AF_INET6 instead of AF_INET. If you're wondering why netifaces uses lists and dictionaries all over the place, it's because a single computer can have multiple NICs, and each NIC can have multiple addresses, and each address has its own set of options.

Harley
A: 

gethostbyaddr() takes an IP address as a parameter, not a hostname, so I'm surprised it's working at all without throwing an exception. If instead you meant gethostbyname(), then your results are more surprising, since that function claims not to support IPv6. Harley's answer explains how to correctly get your IP address.

Adam Rosenfield
+2  A: 

IPv6 is taking precedence over IPv4 as it's the newer family, it's generally what you want if your hostname is associated with multiple families. You should be using getaddrinfo for family independent resolution, here is an example,

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];

Which on a dual-stack configured host gives me the following,

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)
Steve-o