Python网络/CIDR计算

3
我正在构建一个嵌入式网络设备(基于Linux),需要动态生成守护进程配置文件。因此,我需要在Python代码中进行一些网络地址计算,以便生成配置文件。由于我不是程序员,所以我担心一旦设备开始发货,我的模块将无法按照我希望的方式运行。

以下是我目前的代码,它实际上是从这个网站和Google上找到的碎片组合而成的。

是否有更好的方法来查找网络接口的网络地址和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

感谢任何意见,我确实在这方面有些迷茫。如果这不是提供此类反馈的地方,请告诉我。


1
你尝试过使用 netaddripaddr 模块吗? - jfs
1
啊!我想肯定有人已经做过这个了-谢谢@sebastian - tMC
2个回答

4

可以使用汉明重量算法来解决这个问题。从如何计算32位整数中设置的位数?中借鉴,并转换成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

O(log(x)),我认为你正在循环x的位数,而不是x本身。 - DSM

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接