如何获取 python 中网络的所有可能子网 ID?

How to get all possible subnet ID of a network in python?

尝试创建一个函数,该函数 returns 给定网络 ID、子网掩码、默认掩码、感兴趣的八位字节和幻数的所有可能子网 ID 的列表。函数里面感觉classful subnet mask也必须要用但是好像能写个有用的程序

def getAllSubnet(networkID, SubnetMask, classfulSubnetMask, octetInterest, magicNumber):
    classfulSubnetMask = classfulSubnetMask.split('.')
    SubnetMask = SubnetMask.split('.')
    allSubnet = []
    for _ in range(0, int(SubnetMask[octetInterest-1]), magicNumber):
        networkID = networkID.split('.')
        networkID[octetInterest-1] = str(int(networkID[octetInterest-1])+magicNumber)
        networkID = '.'.join(networkID)
        allSubnet.append(networkID)
    return allSubnet

networkID = '16.0.0.0'
subnetRequested = '500'
classfulSubnetMask = '255.0.0.0'
subnetMask = '255.255.128.0'
octetInterest = 3
magicNumber = 128

print(getAllSubnet(networkID, subnetMask, classfulSubnetMask, octetInterest, magicNumber))

网络和主机 ID 的解释

通常有两种类型的IPv4寻址方法,classfulclassless。由于您的示例包含有关 classful 子网划分的信息,因此我假设您想计算给定 IPv4 class 和子网掩码的可能子网数。如果您正在寻找其他内容,我可以根据需要编辑答案。

处理 IPv4 地址(A、B、C、D、E)时有 5 个 classes。每个 class 在 IP 地址的第一个八位字节(前 8 位)中确定。

您可以在此处阅读有关确定 IPv4 class 的更多信息:https://www.tutorialspoint.com/ipv4/ipv4_address_classes.htm

需要注意的是,class完整的 IP 地址在现实世界中不再使用。

话虽如此,根据您提供的示例,您可以按照以下方式分解此信息。

首先是“有类子网掩码”,它将用于确定您的 IP 地址中有多少位构成 class。用于 class 的任何位都不能用于您的子网或主机 ID(主机 ID 是您网络上的实际单个节点)。

然后你有你的“子网掩码”,它告诉你哪些位组成你的子网 ID 和你的主机 ID。

最后,您获得了“网络 ID”,它向我们展示了将用于所有子网和主机 ID 的实际前缀。所以如下:

有类子网掩码: 255.0.0.0(二进制表示:11111111.00000000.00000000.00000000)

子网掩码: 255.255.128.0(二进制表示:11111111.11111111.10000000.00000000)

网络 ID:16.0.0.0(二进制表示:00010000.00000000.00000000.00000000)

我们知道 classful 子网掩码设置的位是为您的网络 ID 保留的(即不能被子网使用),我们也知道子网掩码未设置的位是保留的对于主机(子网掩码末尾的最后 15 个 0)。

这意味着我们要计算出子网掩码中的这些 1 中有多少是 唯一的 子网掩码并且不包含在您的 classful 掩码中。在我们的示例中,十进制表示为“0.255.128.0”,二进制表示为“00000000.11111111.10000000.00000000”。

因此我们有 9 位子网地址 space,如果我们取 2^9,我们将得到 512 个可能的子网 ID。然后我们知道,基于我们的网络 ID 16.0.0.0,我们的子网 ID 范围从 16.0.0.0 到 16.255.128.0。我们还知道每个子网可以有 32,768 台主机。例如,如果您的网络 ID 和子网 ID 等于 16.0.0.0,我们可以拥有 16.0.0.1 到 16.0.127.255 范围内的主机。

使用 Python“ipaddress”库实施解决方案

使用 python 中的“ipaddress”库,我们可以很容易地解决查找所有可能子网的问题。我将 post 示例代码,然后在下面进行解释。

import ipaddress

# Here I've left your variables exactly as they were in case this format is a requirement.
networkID = '16.0.0.0'
subnetRequested = '500'
classfulSubnetMask = '255.0.0.0'
subnetMask = '255.255.128.0'
octetInterest = 3
magicNumber = 128

# Calculate how many 1's are set in the binary forms of both net masks
subnetMaskBits = bin(int(ipaddress.IPv4Address(subnetMask))).count("1")
classfulMaskBits = bin(int(ipaddress.IPv4Address(classfulSubnetMask))).count("1")

# Create an ip_network object using our network address and in CIDR notation
fullAddress = ipaddress.ip_network(networkID + "/" + str(classfulMaskBits))

# Print out all possible subnets against our fulladdress with subnet mask
output = list(fullAddress.subnets(prefixlen_diff=(subnetMaskBits-classfulMaskBits)))

# Print the addresses (note there are going to be a LOT of them)
print (output)

代码相对简单,但有几处可能需要解释。首先,我们计算两种网络掩码二进制形式中 1 的数量。然后我们创建一个 ip_network 对象(python ipaddress 库的一部分)并使用 CIDR 表示法对其进行初始化。

CIDR 代表无类域间路由,在现实世界中用于代替 classful(我们在您的示例中使用的)。我们在这里使用它只是因为它可以让我们轻松计算出我们的子网 ID。

CIDR 表示法类似于 (16.0.0.0/8),其中“/8”表示掩码中 1 的数量。因此,对于完整地址,我们从 classful 子网掩码中传递 1 的数量,即 8。

这个 python 库有一个名为“子网”的函数,它可以完全满足您的问题。您在这里唯一需要知道的是“prefixlen_diff”参数。这个参数基本上是说为我们的子网 ID 保留了多少位。这将等于我们的 classful 掩码中 1 的数量从我们的子网掩码中减去(如上所述)。

更清楚地总结一下:

网络IP地址:16.0.0.0

分类掩码: 255.0.0.0 (11111111.00000000.00000000.00000000)

Classful Mask 1's: 8

网络 IP CIDR 表示法: 16.0.0.0/8

然后对于子网:

子网掩码: 255.255.128.0 (11111111.11111111.10000000.00000000)

子网掩码中的 1: 17

1 的唯一子网掩码: 9 (00000000.11111111.10000000.00000000)

都适用于这行代码:

output = list(fullAddress.subnets(prefixlen_diff=(subnetMaskBits-classfulMaskBits)))

其中 fullAddress 是“16.0.0.0/8”,prefixlen_diff 是 9 (17 - 8)。

我们调用带有列表的子网方法来迭代出所有可能的子网 ID。我们实际上根本不需要 octetInterest 或 magicNumber 变量。

希望我回答了你想问的问题,但如果你正在寻找不同类型的输出,我可以根据需要编辑它。