python实现路由自动聚合(原创)

程序功能:将给定的一组ip地址进行路由聚合,例如:
在这里插入图片描述

较为复杂的例子:

python IPaggregation.py
10.20.0.0/24
10.20.1.0/24
10.20.2.0/24
10.20.3.0/24
10.20.4.0/24
10.20.5.0/24
10.20.6.0/24
10.20.7.0/24
192.168.0.0/24
192.168.1.0/24
192.168.2.0/24
192.168.3.0/24
203.0.113.0/25
203.0.113.128/25
198.51.100.0/24
8.8.8.8/32
45.33.32.0/19
100.64.0.0/10
172.18.5.0/24
203.119.0.0/16


8.8.8.8/32
10.20.0.0/21
45.33.32.0/19
100.64.0.0/10
172.18.5.0/24
192.168.0.0/22
198.51.100.0/24
203.0.113.0/24
203.119.0.0/16

下面是函数的各部分功能介绍,文末附有程序源码。

1. 函数定义

1.1 D2B(IP) 十进制IP转为二进制IP
def D2B(IP):
    tmp = IP.split('.')
    Blist = []
    Blist.append("{:08b}".format(int(tmp[0])))
    Blist.append("{:08b}".format(int(tmp[1])))
    Blist.append("{:08b}".format(int(tmp[2])))
    Blist.append("{:08b}".format(int(tmp[3].split('/')[0])))
    Blist.append(int(tmp[3].split('/')[1]))
    BIPtmp = ''
    for i in Blist:
        BIPtmp += str(i)
    BIP = BIPtmp[:32:] + '/' + BIPtmp[32::]
    return BIP
  • 功能:将十进制的 IPv4 地址(带子网掩码,如 192.168.1.0/24)转换为二进制格式。
  • 步骤:
    1. 将输入的 IP 地址按 . 分割成四部分。
    2. 把每部分转换为 8 位二进制字符串。
    3. 提取子网掩码部分。
    4. 将二进制字符串和子网掩码拼接成完整的二进制 IP 地址。
1.2 B2D(IP) 二进制IP转为十进制IP
def B2D(IP):
    tmp = IP.split('/')
    Dlist = []
    Dlist.append(int(tmp[0][:8:], 2))
    Dlist.append(int(tmp[0][8:16:], 2))
    Dlist.append(int(tmp[0][16:24:], 2))
    Dlist.append(int(tmp[0][24:32:], 2))
    DIPtmp = ''
    for i in Dlist:
        DIPtmp += str(i)
        DIPtmp += '.'
    DIP = DIPtmp[:-1:] + '/' + str(tmp[1])
    return DIP
  • 功能:将二进制的 IPv4 地址(带子网掩码)转换为十进制格式。
  • 步骤:
    1. 将输入的二进制 IP 地址按 / 分割成 IP 部分和子网掩码部分。
    2. 将 IP 部分每 8 位转换为十进制整数。
    3. 将十进制整数用 . 连接起来,并拼接子网掩码,形成完整的十进制 IP 地址。
1.3 check(IN) 校验
def check(IN):
    IN1 = IN.split('/')
    IN2 = IN1[0].split('.')
    IN2.append(IN1[1])
    IN2 = list(map(int, IN2))
    if len(IN2) != 5:
        return False
    for i in IN2[0:4:]:
        if i not in range(0, 256):
            return False
    if IN2[4] not in range(0, 33):
        return False
    return True
  • 功能:检查输入的 IPv4 地址(带子网掩码)格式是否正确。
  • 步骤:
    1. 检查输入的 IP 地址是否能正确分割成 5 个部分(4 个 IP 段和 1 个子网掩码)。
    2. 检查每个 IP 段是否在 0 到 255 之间。
    3. 检查子网掩码是否在 0 到 32 之间。
1.4 打印函数
def print1(element):
    a, b0 = element.split('/')
    b = int(b0)
    print(a[:b], a[b:] + '/' + b0)

def print2(list):
    for i in list:
        print1(i)

def print3(list):
    for i in list:
        print(i)
  • print1(element):将 IP 地址按子网掩码分割成网络前缀和剩余部分并打印。
  • print2(list):对列表中的每个 IP 地址调用 print1 函数进行打印。
  • print3(list):打印列表中的每个元素。
1.5 地址压缩函数
功能概述

aggregation 函数的主要功能是对输入的二进制 IP 地址前缀列表进行聚合(地址压缩)操作。在网络地址规划中,地址聚合可以将多个相邻的 IP 地址块合并成一个更大的地址块,从而减少路由表的条目数量,提高路由效率。该函数通过递归的方式,不断检查相邻的 IP 地址前缀是否可以合并,直到无法再进行合并为止。

代码
def aggregation(INlist=[], flag=1):
    # 如果 flag 为 0,表示上一轮没有发生合并操作,直接返回输入列表
    if flag == 0:
        return INlist
    # 获取列表的长度
    i = len(INlist) - 1
    # 初始化 flag 为 0,表示当前轮次还没有发生合并操作
    flag = 0
    # 从列表末尾开始向前遍历
    while i > 0:
        # 获取当前元素和前一个元素
        IP = INlist[i - 1]
        IP2 = INlist[i]
        # 提取当前元素和前一个元素的前缀(去掉最后一位)
        prefix = IP[:-1]
        prefix2 = IP2[:-1]
        # 如果两个前缀相同,说明可以合并
        if prefix == prefix2:
            # 删除当前元素
            del INlist[i]
            # 将前一个元素更新为合并后的前缀
            INlist[i - 1] = prefix
            # 跳过下一个元素,因为已经合并了
            i -= 2
            # 设置 flag 为 1,表示发生了合并操作
            flag = 1
        else:
            # 如果不能合并,继续向前遍历
            i -= 1
    # 递归调用 aggregation 函数,继续进行合并操作
    return aggregation(INlist, flag)

2. 主函数 main()

def main():
    while True:
        INPUT = input() #输入结束
        if INPUT == '':
            break
        if check(INPUT): #校验&去重
            tail = int(INPUT.split('/')[1])
            pBIP = D2B(INPUT)[0:tail]
            pINjihe.add(pBIP)
        else: #校验未通过
            continue
        pINlist = list(pINjihe)
        pINlist.sort() #排序,方便后续进行地址聚合
    pOUTlist = aggregation(pINlist) #地址聚合
    for i in pOUTlist:
        tail = len(i)
        OUTlist.append(i + (32 - tail) * '0' + '/' + str(tail)) #更改为标准二进制格式
    print3(list(map(B2D, OUTlist))) #更改为十进制格式并输出
  • 主程序逻辑:负责读取输入、校验、去重、排序、聚合和输出结果。
  • 步骤:
    1. 循环读取用户输入,直到输入为空。
    2. 对每个输入进行格式校验,如果校验通过,将其转换为二进制并提取网络前缀,添加到集合 pINjihe 中进行去重。
    3. 将集合转换为列表并排序。
    4. 对排序后的列表进行地址聚合。
    5. 将聚合后的结果补充为标准的 32 位二进制 IP 地址,并添加到 OUTlist 中。
    6. OUTlist 中的二进制 IP 地址转换为十进制格式并输出。

该程序可以帮助用户对输入的 IPv4 地址进行处理,去除重复地址,合并相邻的网络前缀,最终输出经过优化的 IPv4 地址列表。

4. 程序源码

pINjihe=set()
OUTlist=[]
#将十进制IP转化为二进制
def D2B(IP):
    tmp=IP.split('.')
    Blist=[]
    Blist.append("{:08b}".format(int(tmp[0])))
    Blist.append("{:08b}".format(int(tmp[1])))
    Blist.append("{:08b}".format(int(tmp[2])))
    Blist.append("{:08b}".format(int(tmp[3].split('/')[0])))
    Blist.append(int(tmp[3].split('/')[1]))
    BIPtmp=''
    for i in Blist:
        BIPtmp+=str(i)
    BIP=BIPtmp[:32:]+'/'+BIPtmp[32::]
    return BIP
#将二进制IP转化为十进制
def B2D(IP):
    tmp=IP.split('/')
    Dlist=[]
    Dlist.append(int(tmp[0][:8:],2))
    Dlist.append(int(tmp[0][8:16:],2))
    Dlist.append(int(tmp[0][16:24:],2))
    Dlist.append(int(tmp[0][24:32:],2))
    DIPtmp=''
    for i in Dlist:
        DIPtmp+=str(i)
        DIPtmp+='.'
    DIP=DIPtmp[:-1:]+'/'+str(tmp[1])
    return DIP
#IP地址格式检测
def check(IN):
    IN1=IN.split('/')
    IN2=IN1[0].split('.')
    IN2.append(IN1[1])
    IN2=list(map(int,IN2))
    if len(IN2) != 5: #检测格式
        return False
    for i in IN2[0:4:]: #检测IP地址范围
        if i not in range(0,256):
            return False
    if IN2[4] not in range(0,33): #检测网络位范围
        return False
    return True
#各种打印方法
def print1(element):
    a,b0=element.split('/')
    b=int(b0)
    print(a[:b],a[b:]+'/'+b0)
def print2(list):
    for i in list:
        print1(i)
def print3(list):
    for i in list:
        print(i)
#地址压缩函数
def aggregation(INlist=[],flag=1):
    if flag==0:
        return INlist
    i=len(INlist)-1
    flag=0
    while i>0:
        IP=INlist[i-1]
        IP2=INlist[i]
        prefix=IP[:-1]
        prefix2=IP2[:-1]
        if prefix==prefix2:
            del INlist[i]
            INlist[i-1]=prefix
            i-=2
            flag=1
        else:
            i-=1
    return aggregation(INlist,flag)

def main():
    while True:
        INPUT=input()
        if INPUT == '': #输入结束
            break
        if check(INPUT): #校验&去重
            tail=int(INPUT.split('/')[1])
            pBIP=D2B(INPUT)[0:tail]
            pINjihe.add(pBIP)
        else: #校验未通过
            continue
        pINlist=list(pINjihe)
        pINlist.sort() #排序
    pOUTlist=aggregation(pINlist) #压缩
    for i in pOUTlist:
        tail=len(i)
        OUTlist.append( i+ (32-tail)*'0' +'/'+ str(tail) ) #更改为标准二进制格式
    print3(list(map(B2D,OUTlist))) #更改为十进制格式并输出


if __name__ == '__main__':
    main()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值