3

私はPythonで単純なサーバーアプリケーションの作成に取り組んでおり、リッスンソケットをバインドするIPを取得しようとしています。私が見た例では、これを使用しています:

HOST = gethostbyaddr(gethostname())

この後、もう少し処理を加えると、ホスト IP だけが文字列として返されます。これにより、IPv4 アドレスが返されます。しかし、このコードを実行すると、IPv6 アドレスが返されます。なぜこれを行うのですか?どうすれば IPv4 アドレスを取得できますか?

関連する場合、私はWindows VistaとPython 2.5を使用しています

4

3 に答える 3

11

IP アドレスを取得することは、想像以上に困難です。

私が見つけた1つの信頼できる方法について、私が提供したこの回答を確認してください。

クリックしたくない場合の答えは次のとおりです。

モジュールを使用し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、1 台のコンピューターに複数の NIC を配置でき、各 NIC に複数のアドレスを設定でき、各アドレスに独自のオプション セットがあるためです。

于 2009-01-06T04:07:16.900 に答える
5

IPv6 は新しいファミリであるため、IPv4 よりも優先されます。ホスト名が複数のファミリに関連付けられている場合は、通常、IPv6 が必要です。家族に依存しない解決には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)
于 2010-02-06T04:02:29.337 に答える
2

gethostbyaddr()ホスト名ではなく IP アドレスをパラメーターとして使用するため、例外をスローすることなくまったく機能していることに驚いています。代わりに を意味した場合gethostbyname()、その関数は IPv6 をサポートしていないと主張しているため、結果はさらに驚くべきものになります。 Harley's answerは、IP アドレスを正しく取得する方法を説明しています。

于 2009-01-06T04:10:55.783 に答える