Wil*_*n F 36 python sockets ip-address
我的计算机上有多个网络接口卡,每个都有自己的IP地址.
当我使用gethostbyname(gethostname())Python的(内置)socket模块时,它只返回其中一个.我如何得到其他人?
Har*_*mbe 47
使用该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
Run Code Online (Sandbox Code Playgroud)
这可以像这样更具可读性:
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
Run Code Online (Sandbox Code Playgroud)
如果您需要IPv6地址,请使用AF_INET6而不是AF_INET.如果您想知道为什么netifaces在整个地方使用列表和词典,那是因为一台计算机可以有多个NIC,每个NIC可以有多个地址,每个地址都有自己的一组选项.
Nak*_*lon 14
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
Run Code Online (Sandbox Code Playgroud)
小智 9
在netifaces模块的帮助下,所有地址都在一行中:
[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]
Run Code Online (Sandbox Code Playgroud)
仅仅为了完整性,另一种选择是使用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))
Run Code Online (Sandbox Code Playgroud)
你需要的功能是net_if_addrs.即:
import psutil
psutil.net_if_addrs()
Run Code Online (Sandbox Code Playgroud)
结果是这样的(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)]}
Run Code Online (Sandbox Code Playgroud)
(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)]}
Run Code Online (Sandbox Code Playgroud)
注意:由于每个接口可以有多个相同系列的地址,因此dict值是列表.
每个snic都namedtuple包括5个字段:
family:地址系列,AF_INET,AF_INET6或psutil.AF_LINK,它指的是MAC地址.address:主NIC地址(始终设置).netmask:网络掩码地址(可以是None).broadcast:广播地址(可能是None).ptp:代表"点对点"; 它是点对点接口(通常是VPN)上的目标地址.broadcast和ptp是互斥的(可以是None).https://docs.python.org/3.4/library/socket.html#socket.if_nameindex
socket.if_nameindex()
返回网络接口信息(索引 int,名称字符串)元组的列表。如果系统调用失败,则出现 OSError。
可用性:Unix。
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() )
Run Code Online (Sandbox Code Playgroud)
将打印类似以下内容:
['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]
Run Code Online (Sandbox Code Playgroud)