加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 计算给定网络中可用子网的数量

发布时间:2020-12-13 22:53:08 所属栏目:PHP教程 来源:网络整理
导读:我在计算网络中可用子网(或主机)的数量时遇到了以下问题.例如,主子网是/ 24(255.255.255.0),其中包含两个/ 25(255.255.255.128)或四个/ 26(255.255.255.192). 因此,如果已经使用了一个节点,那么将只有一个/ 25个或只有3个/ 26个.那么我应该如何计算可用子网
我在计算网络中可用子网(或主机)的数量时遇到了以下问题.例如,主子网是/ 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-generated):

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 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以类似的方式绘制结果:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读