程序功能:将给定的一组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)转换为二进制格式。 - 步骤:
- 将输入的 IP 地址按
.分割成四部分。 - 把每部分转换为 8 位二进制字符串。
- 提取子网掩码部分。
- 将二进制字符串和子网掩码拼接成完整的二进制 IP 地址。
- 将输入的 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 地址(带子网掩码)转换为十进制格式。
- 步骤:
- 将输入的二进制 IP 地址按
/分割成 IP 部分和子网掩码部分。 - 将 IP 部分每 8 位转换为十进制整数。
- 将十进制整数用
.连接起来,并拼接子网掩码,形成完整的十进制 IP 地址。
- 将输入的二进制 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 地址(带子网掩码)格式是否正确。
- 步骤:
- 检查输入的 IP 地址是否能正确分割成 5 个部分(4 个 IP 段和 1 个子网掩码)。
- 检查每个 IP 段是否在 0 到 255 之间。
- 检查子网掩码是否在 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))) #更改为十进制格式并输出
- 主程序逻辑:负责读取输入、校验、去重、排序、聚合和输出结果。
- 步骤:
- 循环读取用户输入,直到输入为空。
- 对每个输入进行格式校验,如果校验通过,将其转换为二进制并提取网络前缀,添加到集合
pINjihe中进行去重。 - 将集合转换为列表并排序。
- 对排序后的列表进行地址聚合。
- 将聚合后的结果补充为标准的 32 位二进制 IP 地址,并添加到
OUTlist中。 - 将
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()
2064

被折叠的 条评论
为什么被折叠?



