Python使用ipaddress库高效遍历匹配后缀的IPv6地址的实现方法
解决方案
核心问题
- 原有方案的逻辑是先遍历网段内所有地址再做后缀匹配,
/64的IPv6网段包含1844亿亿个地址,遍历完全不可行,效率极低。 - 优化核心思路是完全避免遍历,直接通过位运算构造符合后缀要求的IP地址。
实现思路
- 先将输入的后缀转换为完整展开的IP字符串的后缀,再计算该后缀对应的二进制位数、以及后缀的整数值
- 计算步长:
step = 1 << 后缀位数,也就是每次地址递增的步长刚好覆盖后缀的所有位,保证每次生成的地址后缀都符合要求 - 用网段的网络地址整数值,加上后缀整数值得到第一个符合要求的地址,之后每次加步长即可批量生成所有符合要求的地址
优化后代码
import ipaddress from itertools import islice def suffix_to_mask_and_value(ip_version, suffix): # 构造对应版本的全0展开地址,替换后缀得到样例地址 if ip_version == 4: dummy = ipaddress.IPv4Address('0.0.0.0').exploded suffix_len = len(suffix) sample_addr = dummy[:-suffix_len] + suffix sample_ip = ipaddress.IPv4Address(sample_addr) # 计算后缀占用的二进制位数 mask = 0 for i in range(32): bit_val = 1 << i if (sample_ip._ip & bit_val) == (0 & bit_val): break mask +=1 return mask, sample_ip._ip & ((1 << mask) - 1) else: dummy = ipaddress.IPv6Address('::').exploded suffix_len = len(suffix) sample_addr = dummy[:-suffix_len] + suffix sample_ip = ipaddress.IPv6Address(sample_addr) mask = 0 for i in range(128): bit_val = 1 << i if (sample_ip._ip & bit_val) == (0 & bit_val): break mask +=1 return mask, sample_ip._ip & ((1 << mask) - 1) for address, suffix in zip(['10.10.0.0/16','2A00:7E40:F020::/64'],['.1',':00FF:FE00:0003']): print('===============') network = ipaddress.ip_network(address) print(f'{network.num_addresses} addresses available') print(f'suffix {suffix}') print('===============') suffix_bit_len, suffix_val = suffix_to_mask_and_value(network.version, suffix) step = 1 << suffix_bit_len first_ip = network.network_address._ip | suffix_val max_ip = network.broadcast_address._ip current = first_ip # 输出前2个匹配地址 for _ in range(2): if current > max_ip: break print(ipaddress.ip_address(current)) current += step
运行效果
=============== 65536 addresses available suffix .1 =============== 10.10.0.1 10.10.1.1 =============== 18446744073709551616 addresses available suffix :00FF:FE00:0003 =============== 2a00:7e40:f020::ff:fe00:3 2a00:7e40:f020:1::ff:fe00:3
无需遍历整个网段,不管多大的IPv6网段都可以瞬间返回结果。
内容的提问来源于stack exchange,提问作者rockandska
相关产品推荐
相关产品推荐

