31


9

複数のNICがある場合、どのようにして自分のすべてのIPアドレスを特定するのですか?

コンピュータに複数のネットワークインターフェイスカードがあり、それぞれに独自のIPアドレスがあります。

私がPythonの(組み込みの) socket`モジュールから gethostbyname(gethostname()) `を使うとき、それはそれらの1つだけを返すでしょう。 私は他の人をどうやって手に入れますか?

12 Answer


43


http://alastairs-place.net/netifaces/ [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_INET`の代わりに AF_INET6`を使ってください。 「netifaces」が至るところでリストや辞書を使うのはなぜだろうと思うのであれば、それは単一のコンピュータが複数のNICを持つことができ、各NICが複数のアドレスを持つことができ、各アドレスがそれ自身のオプションのセットを持つからです。


10


インポートソケット
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]


9


`netifaces`モジュールの助けを借りて1行にすべてのアドレス:

[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]


7


完全を期すために、もう1つのオプションはhttps://pypi.python.org/pypi/psutil[psutil]を使用することです。

* tldr; *

import socket
import psutil

def get_ip_addresses(family):
    for interface, snics in psutil.net_if_addrs().items():
        for snic in snics:
            if snic.family == family:
                yield (interface, snic.address)

ipv4s = list(get_ip_addresses(socket.AF_INET))
ipv6s = list(get_ip_addresses(socket.AF_INET6))

説明

あなたが必要とする機能はhttps://pythonhosted.org/psutil/#psutil.net_if_addrs [net_if_addrs]です。 イー。

import psutil
psutil.net_if_addrs()

これは次のようになります(Python 3)。

{'br-ae4880aa80cf': [snic(family=, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
                     snic(family=, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'docker0': [snic(family=, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
             snic(family=, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'eno1': [snic(family=, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'lo': [snic(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
        snic(family=, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
 'wlp2s0': [snic(family=, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
            snic(family=, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

(Python 2):

{'br-ae4880aa80cf': [snic(family=2, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
                     snic(family=17, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'docker0': [snic(family=2, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
             snic(family=17, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'eno1': [snic(family=17, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
 'lo': [snic(family=2, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
        snic(family=17, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
 'wlp2s0': [snic(family=2, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
            snic(family=17, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

:各インタフェースには同じファミリの複数のアドレスを関連付けることができるので、辞書の値はリストです。

それぞれの snic`は5つのフィールドを含むhttps://docs.python.org/3/library/collections.html#collections.namedtuple [ namedtuple`]です。

  • family:アドレスファミリー、AF_INET、AF_INET6または psutil.AF_LINK。MACアドレスを参照します。

  • address:プライマリNICアドレス(常に設定されている)

  • netmask:ネットマスクアドレス(Noneでもかまいません)

  • broadcast:ブロードキャストアドレス(Noneでもかまいません)

  • ptp:「ポイントツーポイント」の略。それは上の宛先アドレスです ポイントツーポイントインターフェイス(通常はVPN)。 broadcastとptpは相互に排他的です(Noneでもかまいません)。


2


socket.if_nameindex()

ネットワークインタフェース情報(index int、name string)タプルのリストを返します。 システムコールが失敗した場合はOSError。

出荷時期:Unix

バージョン3.3の新機能

'' '' '

このコードをPython 3.4、UNIX / Linuxで実行可能にしました

#!/ env / python3.4インポートソケットインポートfcntlインポート構造体

def active_nic_addresses(): "" "コンピュータ上でアクティブなIPv4アドレスのリストを返します。 「」

addresses = [ip.pocket.gethostbyname_ex(socket.gethostname())[2] ipがip.startswith( "127。")でない場合] [:1]

住所を返す

def get_ip_address(NICname):s = socket.socket(socket.AF_INET、socket.SOCK_DGRAM)return socket.inet_ntoa(fcntl.ioctl(s.fileno()、0x8915、#SIOCGIFADDR struct.pack( '256s')、NICname [: 15] .encode( "UTF-8")))[20:24])

def nic_info(): "" "NICとIPv4を含むタプルのリストを返します" = "

socket.if_nameindex()内のixの場合:name = ix [1] ip = get_ip_address(name)

nic.append((name、ip))

返品

__name__ == "__main__"の場合:

print(active_nic_addresses())print(nic_info())

'' '' '

次のように表示されます。

['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]


1


これはLinuxのみですが、非常に単純なレシピがここにありますhttp://code.activestate.com/recipes/439094/

それはおそらく別の答えで言及されている netifacesパッケージに似たコードを使用します(しかし現在のバージョンはここにリンクされています)

socket.getaddrinfo()は、実際にはデバイスのバインドIPアドレスを返しません。 hostsファイルに "127.0.1.1 yourhost.example.com yourhost"という行が含まれている場合(これは一般的な設定です)、getaddrinfoは127.0.1.1のみを返します。


1


これは、すべてのIPv4およびIPv6インターフェースを見つけるためのルーチンです。 前のポスターが指摘したように、socket.gethostbyname_ex()はIPv6では機能しません。Pythonのドキュメントでは socket.getaddressinfo()を使用することをお勧めします。 ]代わりに。

このルーチンはコールバックIPv4インタフェース(127.0.0.1)を追加し、IPv6インタフェースがある場合はコールバックIPv6インタフェース(

1)も追加します。 私のマシンでは、socket.getaddrinfo()がこれらのうちの1つまたは両方をくれますが、他に利用可能なインタフェースがない場合に限られます。

私のニーズのために、私は私の利用可能なインタフェースのそれぞれの指定されたポートでUDPソケットを開こうとしたかった、それがコードがそれに "port"とsocket.SOCK_DGRAMを持っている理由です。 それらを変更しても安全です。 あなたが念頭に置いてポートを持っていない場合。

addrinfo_ipv4 = socket.getaddrinfo(hostname、port、socket.AF_INET、socket.SOCK_DGRAM)addrinfo_ipv6 = [] try:addrinfo_ipv6 = socket.getaddrinfo(hostname、port、socket.AF_INET6、socket.SOCK_DGRAM)を除くsocket.gaierror:pass addfofo = addrinfo_ipv4 addrinfo_ipv4内のf、t、p、cn、aに対する(f、t、a)addrinfo_local = [(socket.AF_INET、socket.SOCK_DGRAM、( '127.0.0.1'、port))] if ifrinfo_ipv6:addrinfo_local。 append(((socket.AF_INET6、socket.SOCK_DGRAM、( ':: 1'、port))))
[addrinfo.append(ai) for ai in addrinfo_local if ai not in addrinfo]


1


このスニペットはシステムで利用可能なすべてのIPV4アドレスのリストを与えます。

netifacesからインターフェースをインポートするimport interfaces、ifaddresses、AF_INET

links = filter(なし、(interfaces())のxの場合は(ifaddresses(x).get(AF_INET))links = itertools.chain(* links)ip_addresses = [リンクのxのx ['addr']


0


あなたは直接すべてのIP設定されたIPアドレスを得るべきです。 ifconfigを実行してその出力を解析すること( ifconfigがPythonで直接行うことをすることも可能です)、https://stackoverflow.com/questions/259389/finding -an-ip-from-an-interface-name [C言語で行われる方法を参照。 ホスト名が必要な場合は、gethostbyaddrを使用してください。


0


これはかなり簡単にできます。

インポートnetifaces

netifaces.interfaces()のインターフェースの場合:print netifaces.ifaddresses(interface)

詳細については、https://pypi.python.org/pypi/netifaces [netifaces documentation]を参照してください。