Python 网络/CIDR 计算
我正在开发一个基于Linux的嵌入式网络设备,遇到了需要动态生成守护进程配置文件的情况。因此,我需要在用Python编写这些配置文件的代码中进行一些网络地址的计算。因为我不是程序员,所以我担心自己写的模块在设备开始出货后可能无法正常工作。
下面是我目前的进展,都是根据我在这个网站和谷歌上找到的资料拼凑起来的。
有没有更好的方法来找到网络接口的网络地址和CIDR?把子网掩码转换成二进制字符串并计算其中的1的数量似乎不太优雅。
import socket
import fcntl
import struct
SIOCGIFNETMASK = 0x891b
SIOCGIFADDR = 0x8915
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def _GetIfaceMask(iface):
return struct.unpack('L', fcntl.ioctl(s, SIOCGIFNETMASK, struct.pack('256s', iface))[20:24])[0]
def _GetIfaceAddr(iface):
return struct.unpack('L', fcntl.ioctl(s, SIOCGIFADDR, struct.pack('256s', iface[:15]))[20:24])[0]
def GetIfaceNet(iface):
net_addr = _GetIfaceAddr(iface) & _GetIfaceMask(iface)
return socket.inet_ntoa(struct.pack('L', net_addr))
def GetIfaceCidr(iface):
bin_str = bin(_GetIfaceMask(iface))[2:]
cidr = 0
for c in bin_str:
if c == '1': cidr += 1
return cidr
谢谢大家的建议,我真的有点迷茫。如果这个地方不适合这种反馈,请告诉我。
2 个回答
4
这个问题可以用一种叫做汉明重量的算法来解决。这个算法是从如何计算32位整数中1的个数?上借来的,然后用Python语言写成了代码:
def number_of_set_bits(x):
x -= (x >> 1) & 0x55555555
x = ((x >> 2) & 0x33333333) + (x & 0x33333333)
x = ((x >> 4) + x) & 0x0f0f0f0f
x += x >> 8
x += x >> 16
return x & 0x0000003f
还有一种更易读的解决方案(但运行时间是O(log x)
):
def number_of_set_bits(x):
n = 0
while x:
n += x & 1
x = x >> 1
return n
2
你可以看看iptools这个Python模块,地址是 http://code.google.com/p/python-iptools/。它可以把长整型的IP地址转换成点分格式的IP地址,反过来也可以。