문제

내 컴퓨터에 여러 개의 네트워크 인터페이스 카드가 있으며 각각 자체 IP 주소가 있습니다.

내가 사용할 때 gethostbyname(gethostname()) Python 's (내장)에서 socket 모듈은 그 중 하나만 반환합니다. 다른 사람들은 어떻게 얻습니까?

도움이 되었습니까?

해결책

사용 netifaces 기준 치수. 네트워킹은 복잡하기 때문에 Netiface를 사용하는 것은 약간 까다로울 수 있지만 여기에 원하는 작업을 수행하는 방법은 다음과 같습니다.

>>> 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에는 여러 개의 주소가있을 수 있으며 각 주소에는 고유 한 옵션이 있습니다.

다른 팁

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.

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

설명

필요한 기능은입니다 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)]}

(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)]}

메모: 각 인터페이스와 관련된 동일한 제품군의 주소가 둘 이상을 가질 수 있으므로 DICT 값은 목록입니다.

snic a namedtuple 여기에는 5 개의 필드가 포함됩니다.

  • family: 주소 패밀리, AF_INET, AF_INET6 또는 PSUTIL.AF_LINK 중 하나는 MAC 주소를 나타냅니다.
  • address: 기본 NIC 주소 (항상 설정).
  • netmask: netmask 주소 (없음).
  • broadcast: 방송 주소 (없음).
  • ptp:“포인트로 포인트”를 나타냅니다. 포인트 간 인터페이스 (일반적으로 VPN)의 대상 주소입니다. 방송 및 PTP는 상호 배타적입니다 (없음).

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

socket.if_nameindex ()

네트워크 인터페이스 정보 목록 (색인 int, 이름 문자열) 튜플 목록을 반환합니다. OSERROR 시스템 호출이 실패하면.

가용성 : 유닉스.

버전 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')]

Linux 전용이지만 여기에는 매우 간단한 레시피가 있습니다. http://code.activestate.com/recipes/439094/

아마도 비슷한 코드를 사용합니다 Netifaces 패키지 다른 답변에 언급되었습니다 (그러나 현재 버전 링크)

socket.getAddrinfo ()는 실제로 장치의 바운드 IP 주소를 반환하지 않습니다. 호스트 파일에 일반적인 구성 인 "127.0.1.1 yourhost.example.com YourHost"가있는 줄이있는 경우 getAddrinfo는 127.0.1.1 만 반환합니다.

다음은 모든 IPv4 및 IPv6 인터페이스를 찾기위한 루틴입니다. 이전 포스터가 지적한 것처럼 Socket.gethostbyName_ex ()는 IPv6에서 작동하지 않으며 Python 문서는 하나의 사용을 권장합니다. 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]

IfConfig를 실행하고 출력을 구문 분석하여 모든 IP 구성 IP 주소 (예 : 모든 IP 구성 IP 주소를 직접 얻어야합니다) ifconfig는 파이썬에서 직접 수행합니다, c에서 어떻게 수행되는지보십시오). 호스트 이름을 원한다면 gethostbyaddr을 사용하십시오.

다음과 같이 쉽게 쉽게 할 수 있습니다.

import netifaces

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

자세한 정보는 다음을 찾을 수 있습니다 Netifaces 문서.

@Harley Holcombe의 답변은 실행 가능하다고 생각하지만 IP가없는 가상 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

LAN IPv4 만 반환합니다

이 스레드에서 알 수 있듯이 동일한 결과를 획득하는 방법에는 여러 가지가 있습니다. 제안 된 방법은 빌드 인 패밀리 필터를 활용하는 것입니다. getaddrinfo() 표준화 된 튜플을 구문 분석하십시오.

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