在計算網絡中可用子網(或主機)的數量時,存在以下問題。例如,主子網是/ 24(255.255.255.0),其中包含兩個/ 25(255.255.255.128)或四個/ 26(255.255.255.192)。計算給定網絡中可用子網的數量
所以,如果一個節點已被使用,將只有一個/ 25或只有3次/ 26。那麼我應該如何計算可用子網的數量。換句話說,如何獲得剩餘數量和類型。 我想在PHP中執行此算法。
在計算網絡中可用子網(或主機)的數量時,存在以下問題。例如,主子網是/ 24(255.255.255.0),其中包含兩個/ 25(255.255.255.128)或四個/ 26(255.255.255.192)。計算給定網絡中可用子網的數量
所以,如果一個節點已被使用,將只有一個/ 25或只有3次/ 26。那麼我應該如何計算可用子網的數量。換句話說,如何獲得剩餘數量和類型。 我想在PHP中執行此算法。
我用python解決了這個問題(所有的代碼都附加了,整個腳本到最後),但是我確定PHP的解決方案存在類似的庫。由於這是舊的,沒有解決方案發布,我猜任何解決方案(在這種情況下,Python解決方案)比沒有解決方案好。
該腳本由兩個功能組成,一個使用BFS計算「主」子網內的可用子網,另一個使用graphviz創建pdf圖形。
我使用的算法是一個非常簡單的BFS。它基本上從頂級子網(「main」,/ 24)開始,並查明是否有任何已使用(「已採納」)的子網與其重疊/匹配。如果它們中的任何一個都存在,則該算法排隊它的「孩子」(/ 25)以在相同的過程中被檢查。如果算法遇到沒有「被採納」子的子網,它將被標記爲「可用」。如果它擊中與「採取」完全匹配的子網,則將其標記爲「採取」。在任何其他情況下,迭代繼續。
可視化的繪製過程是相同的。
這裏是腳本描述(argparse生成):
usage: script.py [-h] -m M -t TAKEN [TAKEN ...] -o OUTPUT
optional arguments:
-h, --help show this help message and exit
-m M, --m M main subnet to check
-t TAKEN [TAKEN ...], --taken TAKEN [TAKEN ...]
taken subnets
-o OUTPUT, --output OUTPUT
graphviz output file name (.pdf)
使用參數運行腳本:
subnet_script.py -m 255.255.255.0/24 -t 255.255.255.192/26 -o test
給出了這些結果:
做有點像更有趣的事:
script.py -m 255.255.255.0/24 -t 255.255.255.192/26 255.255.255.128/30 -o test
給出了這些結果:
我用過的ipaddress,queue和graphviz(對於Python)模塊,以及argparse使腳本更好用。
第一功能:
def make_subnet_graph(main, taken_subnets, available_subnets, filename):
g = graphviz.Graph()
q = queue.Queue()
q.put(main)
g.node(str(main))
while q.qsize() > 0:
subnet = q.get()
for sub_subnet in subnet.subnets():
if sub_subnet in available_subnets:
# draw as available (green)
g.node(str(sub_subnet), _attributes={"color": "green"})
g.edge(str(sub_subnet), str(subnet))
continue
if sub_subnet in taken_subnets:
# draw as taken (red)
g.node(str(sub_subnet), _attributes={"color": "red"})
g.edge(str(sub_subnet), str(subnet))
continue
# has mixed type subnets (taken/available) - go deeper
g.node(str(sub_subnet))
g.edge(str(sub_subnet), str(subnet))
q.put(sub_subnet)
# write file
g.render(filename)
整個事情與argparse一起:
#!/usr/bin/env python3.4
import ipaddress
import argparse
import queue
import graphviz
def get_available_subnets(main, taken):
# we assume no subnets are available intially
available = []
q = queue.Queue()
# add first node for expansion in the BFS process
q.put(main)
while q.qsize() > 0:
subnet = q.get()
for taken_subnet in taken:
if taken_subnet.compare_networks(subnet) == 0:
# found matching subnet in taken, stop expanding
print("similar: %s and %s" % (subnet, taken_subnet))
break
if taken_subnet.overlaps(subnet):
# still has overlaps somewhere in children, keep expanding
print("overlaps: %s and %s" % (subnet, taken_subnet))
for sub_subnet in subnet.subnets():
q.put(sub_subnet)
break
else:
# no overlaps with taken - this subnet is entirely available
available.append(subnet)
return available
def make_subnet_graph(main, taken_subnets, available_subnets, filename):
g = graphviz.Graph()
q = queue.Queue()
q.put(main)
g.node(str(main))
while q.qsize() > 0:
subnet = q.get()
for sub_subnet in subnet.subnets():
if sub_subnet in available_subnets:
# draw as available (green)
g.node(str(sub_subnet), _attributes={"color": "green"})
g.edge(str(sub_subnet), str(subnet))
continue
if sub_subnet in taken_subnets:
# draw as taken (red)
g.node(str(sub_subnet), _attributes={"color": "red"})
g.edge(str(sub_subnet), str(subnet))
continue
# has mixed type subnets (taken/available) - go deeper
g.node(str(sub_subnet))
g.edge(str(sub_subnet), str(subnet))
q.put(sub_subnet)
# write file
g.render(filename)
if "__main__" == __name__:
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--m', help='main subnet to check', required=True)
parser.add_argument('-t', '--taken', nargs='+', help='taken subnets', required=True)
parser.add_argument('-o', '--output', help='graphviz output file name (.pdf)', required=True)
args = parser.parse_args()
taken = [ipaddress.IPv4Network(subnet) for subnet in args.taken]
main = ipaddress.IPv4Network(args.m)
available = get_available_subnets_set(main, taken)
make_subnet_graph(main, taken, available, args.output)
def get_available_subnets_set(main, taken):
# we assume no subnets are available intially
available = []
q = queue.Queue()
# add first node for expansion in the BFS process
q.put(main)
while q.qsize() > 0:
subnet = q.get()
for taken_subnet in taken:
if taken_subnet.compare_networks(subnet) == 0:
# found matching subnet in taken, stop expanding
print("similar: %s and %s" % (subnet, taken_subnet))
break
if taken_subnet.overlaps(subnet):
# still has overlaps somewhere in children, keep expanding
print("overlaps: %s and %s" % (subnet, taken_subnet))
for sub_subnet in subnet.subnets():
q.put(sub_subnet)
break
else:
# no overlaps with taken - this subnet is entirely available
available.append(subnet)
return set(available)
第二功能以類似方式使用的graphviz繪製結果