كيف يمكنني تحديد كافة عناوين IP الخاصة بي عندما يكون لدي بطاقات NIC متعددة؟

StackOverflow https://stackoverflow.com/questions/270745

  •  06-07-2019
  •  | 
  •  

سؤال

لدي عدة بطاقات واجهة شبكة على جهاز الكمبيوتر الخاص بي، ولكل منها عنوان IP الخاص بها.

عندما أستخدم gethostbyname(gethostname()) من بايثون (مدمج) socket الوحدة، وسوف يعود واحد منهم فقط.كيف أحصل على الآخرين؟

هل كانت مفيدة؟

المحلول

واستخدم 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 يمكن أن يكون لها عناوين متعددة، ولكل عنوان لديها مجموعة من الخيارات.

نصائح أخرى

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

جميع العناوين في سطر واحد مع مساعدة من وحدة netifaces:

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

فقط من أجل الاكتمال، سيكون هناك خيار آخر هو الاستخدام psutil.

تلدر؛

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

توضيح

الوظيفة التي تحتاجها هي net_if_addrs.أي.:

import psutil
psutil.net_if_addrs()

مما يؤدي إلى شيء مثل هذا (Python 3):

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

(بيثون 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 هو namedtuple والذي يتضمن 5 مجالات:

  • family:عائلة العناوين، إما AF_INET أو AF_INET6 أو psutil.AF_LINK، والتي تشير إلى عنوان MAC.
  • address:عنوان NIC الأساسي (المضبوط دائمًا).
  • netmask:عنوان قناع الشبكة (قد يكون لا شيء).
  • broadcast:عنوان البث (قد يكون لا شيء).
  • ptp:تعني "نقطة إلى نقطة"؛إنه عنوان الوجهة على واجهة نقطة إلى نقطة (عادةً VPN).البث وptp متنافيان (قد لا يكونا).

https://docs.python.org/3.4/library/socket.html#socket.if_nameindex

المقبس.if_nameindex()

قم بإرجاع قائمة بمعلومات واجهة الشبكة (الفهرس، سلسلة الاسم) من الصفوف.خطأ OSE في حالة فشل استدعاء النظام.

التوفر:يونكس.

الجديد في الإصدار 3.3.


قام بإنشاء هذا الكود القابل للتشغيل على Python 3.4 و UNIX / Linux

#!/env/python3.4
import socket
import fcntl
import struct

def active_nic_addresses():
    """
    Return a list of IPv4 addresses that are active on the computer.
    """

    addresses = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]

    return addresses

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():
    """
    Return a list with tuples containing NIC and IPv4
    """
    nic = []

    for ix in socket.if_nameindex():
        name = ix[1]
        ip = get_ip_address( name )

        nic.append( (name, ip) )

    return nic

if __name__ == "__main__":

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

سيتم طباعة شيء مثل:

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

وانها لينكس فقط، ولكن هناك وصفة بسيطة جدا هنا http://code.activestate.com / وصفات / 439094 /

وربما يستخدم رمز مشابهة لما netifaces حزمة المذكورة في إجابة أخرى (ولكن التيار إصدار مرتبطة هنا)

ووsocket.getaddrinfo () لا فعلا إرجاع عنوان IP منضم للجهاز. إذا احتوى ملف المضيفين خط مع "127.0.1.1 yourhost.example.com yourhost"، وهو تكوين المشترك، getaddrinfo في لن يؤدي الا الى العودة 127.0.1.1.

وهنا هو روتين للعثور على جميع الواجهات IPv4 و IPv6. كما أشار ملصق سابقة بها، socket.gethostbyname_ex () لا يعمل ل IPv6، ويوصي وثائق بيثون واحد استخدام <لأ href = "http://docs.python.org/library/socket.html#socket.getaddrinfo" يختلط = "نوفولو noreferrer"> socket.getaddressinfo () بدلا من ذلك.

وهذا الروتين يضيف واجهة رد عناوين IPv4 (127.0.0.1)، وإذا كان هناك أي واجهات الإصدار IPv6 ثم فإنه يضيف أيضا ب IPv6 واجهة رد (:: 1). على الجهاز الخاص بي، socket.getaddrinfo () سوف تعطيني واحد أو كل من هذه ولكن فقط إذا ليس لدي أي واجهات الأخرى المتاحة.

لاحتياجات بلدي، كنت أرغب في محاولة لفتح مأخذ توصيل UDP على منفذ محدد على كل من بلدي واجهات المتاحة، وهذا هو السبب رمز له "الميناء" و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)
except socket.gaierror:
    pass
addrinfo = [(f,t,a) for f,t,p,cn,a in addrinfo_ipv4+addrinfo_ipv6]
addrinfo_local = [(socket.AF_INET,socket.SOCK_DGRAM,('127.0.0.1',port))]
if addrinfo_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]

وهذا المقتطف سوف يعطي قائمة من كافة عناوين IPV4 المتوفرة في النظام.

import itertools
from netifaces import interfaces, ifaddresses, AF_INET

links = filter(None, (ifaddresses(x).get(AF_INET) for x in interfaces()))
links = itertools.chain(*links)
ip_addresses = [x['addr'] for x in links]

ويجب عليك الحصول على مباشرة كافة عناوين IP تكوين IP، على سبيل المثال عن طريق تشغيل إفكونفيغ وتحليل انتاجها (أنه من الممكن أيضا أن تفعل ما يفعل إفكونفيغ مباشرة في بيثون ، نرى كيف يتم ذلك في C ). إذا كنت تريد أسماء المضيفين، واستخدام gethostbyaddr.

ويمكنك القيام بذلك بسهولة إلى حد ما مثل هذا:

import netifaces

for interface in netifaces.interfaces():
    print netifaces.ifaddresses(interface)

لمزيد من المعلومات يمكنك البحث عن و .

وأعتقد أن الجوابHarley هولكومب هي قابلة للتطبيق، ولكن إذا كان لديك بعض بطاقات NIC الظاهري دون الملكية الفكرية سيكون خطأ. لذلك هذا هو ط تعديل:

def get_lan_ip():
for interface in interfaces():
    try:
        for link in ifaddresses(interface)[AF_INET]:
            if str(link['addr']).startswith("172."):
                return str(link['addr'])
    except:
        pass

وهذا سيعود فقط شبكة الاتصال المحلية من IPv4

وكما يشير هذا الموضوع، وهناك الكثير من الطرق لacchive نفس النتيجة، في طريقي المقترح هو للاستفادة من البناء في الأسرة مرشح في getaddrinfo() وتحليل الصفوف (tuple) موحدة مثل ذلك:

from socket import getaddrinfo, AF_INET, gethostname

for ip in getaddrinfo(host=gethostname(), port=None, family=AF_INET):   
    print(ip[4][0])

والناتج مثال:

192.168.55.1
192.168.170.234
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top