12.2. ipaddress — 互联网地址
目标:用于处理互联网协议 (IP) 地址的类
ipaddress
模块包含用于处理 IPv4 和 IPv6 网络地址的类。这个类支持验证,查找网络上的地址和主机以及其他的常见操作。
地址
最基本的对象用来表示网络地址本身。将字符串,数字,或者字节序列传递给 ip_address()
来构造一个地址。根据使用的地址类型,返回值将是 IPv4
或者 IPv6
的实例。
ipaddress_addresses.py
import binascii
import ipaddress
ADDRESSES = [
'10.9.0.6',
'fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa',
]
for ip in ADDRESSES:
addr = ipaddress.ip_address(ip)
print('{!r}'.format(addr))
print(' IP version:', addr.version)
print(' is private:', addr.is_private)
print(' packed form:', binascii.hexlify(addr.packed))
print(' integer:', int(addr))
print()
这两个类都可以为不同目的提供地址的各种表示,并回答基本断言,比如地址是保留给多播通信或者保留在专用网络上。
$ python3 ipaddress_addresses.py
IPv4Address('10.9.0.6')
IP version: 4
is private: True
packed form: b'0a090006'
integer: 168361990
IPv6Address('fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa')
IP version: 6
is private: True
packed form: b'fdfd87b5b4755e3eb1bce121a8eb14aa'
integer: 337611086560236126439725644408160982186
网络
一个网络由一组地址所定义。它通常用一个基本地址和一个掩码来表示地址中的那一部分代表网络,剩余的那一部分代表网络里面的地址。掩码可以是精准的,也可以是如下例一样简单的使用前缀值。
ipaddress_networks.py
import ipaddress
NETWORKS = [
'10.9.0.0/24',
'fdfd:87b5:b475:5e3e::/64',
]
for n in NETWORKS:
net = ipaddress.ip_network(n)
print('{!r}'.format(net))
print(' is private:', net.is_private)
print(' broadcast:', net.broadcast_address)
print(' compressed:', net.compressed)
print(' with netmask:', net.with_netmask)
print(' with hostmask:', net.with_hostmask)
print(' num addresses:', net.num_addresses)
print()
与地址相同,对 IPv4 和 IPv6 来说有两种网络类可供使用。每一个类都提供了用于访问网络相关的值的属性和方法,例如广播地址和可供主机使用的网络地址。
$ python3 ipaddress_networks.py
IPv4Network('10.9.0.0/24')
is private: True
broadcast: 10.9.0.255
compressed: 10.9.0.0/24
with netmask: 10.9.0.0/255.255.255.0
with hostmask: 10.9.0.0/0.0.0.255
num addresses: 256
IPv6Network('fdfd:87b5:b475:5e3e::/64')
is private: True
broadcast: fdfd:87b5:b475:5e3e:ffff:ffff:ffff:ffff
compressed: fdfd:87b5:b475:5e3e::/64
with netmask: fdfd:87b5:b475:5e3e::/ffff:ffff:ffff:ffff::
with hostmask: fdfd:87b5:b475:5e3e::/::ffff:ffff:ffff:ffff
num addresses: 18446744073709551616
一个网络实例是可迭代对象,并且返回网络上的地址。
ipaddress_network_iterate.py
import ipaddress
NETWORKS = [
'10.9.0.0/24',
'fdfd:87b5:b475:5e3e::/64',
]
for n in NETWORKS:
net = ipaddress.ip_network(n)
print('{!r}'.format(net))
for i, ip in zip(range(3), net):
print(ip)
print()
这个例子仅仅打印出了一部分地址,因为 IPv6 网络可以包含远超适宜输出的地址数量的地址。
$ python3 ipaddress_network_iterate.py
IPv4Network('10.9.0.0/24')
10.9.0.0
10.9.0.1
10.9.0.2
IPv6Network('fdfd:87b5:b475:5e3e::/64')
fdfd:87b5:b475:5e3e::
fdfd:87b5:b475:5e3e::1
fdfd:87b5:b475:5e3e::2
并不是所有通过对网络进行迭代产生的网络地址都是可用的。举个例子,网络的基地址和广播地址都是包含在迭代的地址当中,这些地址都是不可用的。如果想要找到网络上常规主机可用的地址需要用 hosts()
方法来返回一个生成器。
ipaddress_network_iterate_hosts.py
import ipaddress
NETWORKS = [
'10.9.0.0/24',
'fdfd:87b5:b475:5e3e::/64',
]
for n in NETWORKS:
net = ipaddress.ip_network(n)
print('{!r}'.format(net))
for i, ip in zip(range(3), net.hosts()):
print(ip)
print()
与上一个例子的输出进行比较可以看出, 这个例子中的主机地址并不包括在整个网络上迭代时生成的第一个值。
$ python3 ipaddress_network_iterate_hosts.py
IPv4Network('10.9.0.0/24')
10.9.0.1
10.9.0.2
10.9.0.3
IPv6Network('fdfd:87b5:b475:5e3e::/64')
fdfd:87b5:b475:5e3e::1
fdfd:87b5:b475:5e3e::2
fdfd:87b5:b475:5e3e::3
NETWORKS 除了最基本的迭代器协议之外,还支持了操作符 in
去判断一个地址是否是网络的一部分。
ipaddress_network_membership.py
import ipaddress
NETWORKS = [
ipaddress.ip_network('10.9.0.0/24'),
ipaddress.ip_network('fdfd:87b5:b475:5e3e::/64'),
]
ADDRESSES = [
ipaddress.ip_address('10.9.0.6'),
ipaddress.ip_address('10.7.0.31'),
ipaddress.ip_address(
'fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa'
),
ipaddress.ip_address('fe80::3840:c439:b25e:63b0'),
]
for ip in ADDRESSES:
for net in NETWORKS:
if ip in net:
print('{}\nis on {}'.format(ip, net))
break
else:
print('{}\nis not on a known network'.format(ip))
print()
in
是用网络掩码去测试地址,所以它比扩展完整的网络地址的列表更有效率。
$ python3 ipaddress_network_membership.py
10.9.0.6
is on 10.9.0.0/24
10.7.0.31
is not on a known network
fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa
is on fdfd:87b5:b475:5e3e::/64
fe80::3840:c439:b25e:63b0
is not on a known network
接口
一个网络接口表示网络上一个特定的地址,它可以由一个主机地址和一个网络前缀或者网络掩码表示。
ipaddress_interfaces.py
import ipaddress
ADDRESSES = [
'10.9.0.6/24',
'fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa/64',
]
for ip in ADDRESSES:
iface = ipaddress.ip_interface(ip)
print('{!r}'.format(iface))
print('network:\n ', iface.network)
print('ip:\n ', iface.ip)
print('IP with prefixlen:\n ', iface.with_prefixlen)
print('netmask:\n ', iface.with_netmask)
print('hostmask:\n ', iface.with_hostmask)
print()
接口对象包含访问完整网络和特定地址的属性,同时还提供了几种不同的方式表示接口和网络掩码。
$ python3 ipaddress_interfaces.py
IPv4Interface('10.9.0.6/24')
network:
10.9.0.0/24
ip:
10.9.0.6
IP with prefixlen:
10.9.0.6/24
netmask:
10.9.0.6/255.255.255.0
hostmask:
10.9.0.6/0.0.0.255
IPv6Interface('fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa/64')
network:
fdfd:87b5:b475:5e3e::/64
ip:
fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa
IP with prefixlen:
fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa/64
netmask:
fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa/ffff:ffff:ffff:ffff::
hostmask:
fdfd:87b5:b475:5e3e:b1bc:e121:a8eb:14aa/::ffff:ffff:ffff:ffff
参考
- ipaddress 库标准文档
- PEP 3144 -- IP 地址操作 Python 标准库文档
- ipaddress 库介绍
- 维基百科: IP 地址 -- IP 地址和网络介绍。
- Computer Networks (5th Edition) -- By Andrew S. Tanenbaum and David J. Wetherall. Published by Pearson, 2010. ISBN-10: 0132126958
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。