首页 > 解决方案 > 如何在python中获取网络的所有可能的子网ID?

问题描述

尝试创建一个函数,该函数返回给定网络 ID、子网掩码、默认掩码、感兴趣的八位字节和幻数的所有可能子网 ID 的列表。在函数里面,我觉得有类子网掩码也必须使用,但似乎可以编写一个有用的程序。

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))

标签: pythonsubnet

解决方案


网络和主机 ID 说明

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

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

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

应该注意的是,在实际场景中不再使用有类 IP 寻址。

话虽如此,根据您提供的示例,您将如何分解这些信息。

首先是“<strong>Classful Subnet Mask”,用于确定您的 IP 地址有多少位构成该类别。用于该类的任何位都不能用于您的子网或主机 ID(主机 ID 是网络上实际的单个节点)。

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

最后,您有您的“<strong>Network 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)

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

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

因此,我们有 9 位子网寻址空间,如果我们取 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' 库,我们可以很容易地解决查找所有可能子网的问题。我将发布示例代码,然后在下面进行解释。

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

CIDR 符号看起来像这样(16.0.0.0/8),其中“/8”表示掩码中 1 的数量。因此,对于完整地址,我们从有类子网掩码中传入 1 的个数,即 8。

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

更清楚地总结一下:

网络 IP 地址: 16.0.0.0

有类掩码: 255.0.0.0 (11111111.00000000.00000000.00000000)

经典面具 1 个: 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_diff9 (17 - 8)。

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

希望我回答了您试图提出的问题,但如果您正在寻找不同类型的输出,我可以根据需要对其进行编辑。


推荐阅读