2009-01-06 23 views
3

我正在努力使用python製作一個簡單的服務器應用程序,並且我試圖讓IP綁定偵聽套接字。我看的一個例子使用這個:爲什麼gethostbyaddr(gethostname())返回我的IPv6 IP?

HOST = gethostbyaddr(gethostname()) 

在這之後再多處理一次,它應該給我一個主機IP作爲字符串。這應該返回IPv4地址。但是當我運行這個代碼時,它會返回我的IPv6地址。它爲什麼這樣做,如何獲得我的IPv4地址?

如果其相關的,我使用的是Windows Vista和Python 2.5的

回答

11

讓您的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可以有多個地址,並且每個地址都有自己的一組選項。

0

gethostbyaddr()需要一個IP地址作爲參數,而不是主機名,所以我很驚訝它的工作根本沒有拋出異常。如果你的意思是gethostbyname(),那麼你的結果更令人驚訝,因爲該函數聲稱不支持IPv6。 Harley's answer說明如何正確獲取您的IP地址。

5

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) 
相關問題