用Python开发一个交互式网络和IP地址计算器( 二 )


用Python开发一个交互式网络和IP地址计算器

文章插图
 
  • 这里我们用abs()这个绝对值函数来计算有多少可用的IP地址,原因是当子网掩码为/32 (255.255.255.255)时,no_of_zeros = 0,如果不用abs()的话, 2 ** 0 - 2 结果为负1,用abs()则可以将其转换成正1, 演示如下:

用Python开发一个交互式网络和IP地址计算器

文章插图
 
D.
我们知道网络IP和广播IP是两个很重要的概念,在给定一个IP地址及其子网掩码后,计算该网段的网络IP和广播IP的方法想必大家都知道,即将IP地址和子网掩码分别转换成二进制,然后将两者对比,看子网掩码的二进制有多少个1,那么IP地址的二进制就从左至右保留多少位,剩下的部分全部以0填充,即可得到网络IP的二进制地址,如果剩下部分全部以1填充,则得到广播IP的二进制地址(这里就不画图演示了,这些都是网工最最最基础的知识点,不懂的回去把CCENT或CCNA的书重新翻出来读) 。下面我们在Python中演示如何实现找出一个指定IP所在网段的网络IP和广播IP(代码接前文,以前文给定的IP地址192.168.1.1和子网掩码255.255.255.0为例):
用Python开发一个交互式网络和IP地址计算器

文章插图
 
  • 在使用上面提到的填充0的方法得到了网络IP的二进制地址(11000000101010000000000100000000)后,为了将它转换成四个八位组的十进制形式,这里我们巧用for循环配合range(0,32,8)来将该网络IP的二进制地址切成四段,每段含8个二进制数字,作为元素被依次添加进net_ip_octets这个空列表,最后使用带参数2的int()函数将它们转换成十进制,然后再将这四个十进制数字作为元素依次添加进net_ip_address这个空列表,最后配合".".join()将给列表转化为字符串,即得到了网络IP:192.168.1.0
依葫芦画瓢,从下面这段代码中我们又得到了广播IP: 192.168.1.255
用Python开发一个交互式网络和IP地址计算器

文章插图
 
E.最后我们来谈谈反掩码,所谓反掩码就是将子网掩码的二进制里的1换成0,将0换成1,比如255.255.255.0的二进制为11111111.11111111.11111111.00000000,它的反掩码即为00000000.00000000.00000000.11111111,也就是0.0.0.255 。在Python里我们可以这样表示(代码接上文):
用Python开发一个交互式网络和IP地址计算器

文章插图
 
最后来看下该交互式的网络和IP地址计算器的最终代码:
#coding=utf-8import systry:while True: #判断用户输入的IP是否符合规范,如果不规范则while循环反复询问,直到用户输入正确IP地址为止 。ip_address = input("输入要查询的IP地址: ")ip_octets = ip_address.split('.') #将IP地址用split()转换成列表,该列表有4个元素,分别代表用户输入的IP地址的4个8位字段 。#0.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16以及Class D这些保留IP地址均不是有效的IPif (len(ip_octets) == 4) and (1 <= int(ip_octets[0]) <= 223) and (int(ip_octets[0]) != 127) and (int(ip_octets[0]) != 169 or int(ip_octets[1]) != 254) and (0 <= int(ip_octets[1]) <= 255 and 0 <= int(ip_octets[2]) <= 255 and 0 <= int(ip_octets[3]) <= 255):breakelse:print("n不是有效的IP地址,请重新输入n")continuemasks = [255, 254, 252, 248, 240, 224, 192, 128, 0] #将所有有效的子网掩码的十进制数字归纳进一个列表,用于验证用户输入的子网掩码是否合乎规范while True: #判断用户输入的子网掩码是否符合规范,如果不规范则while循环反复询问,直到用户输入正确子网掩码为止 。subnet_mask = input("输入子网掩码: ")mask_octets = subnet_mask.split('.') #将子网掩码用split()转换成列表,该列表有4个元素,分别代表用户输入的子网掩码的4个8位字段 。#支持/0 - /32所有子网掩码if (len(mask_octets) == 4) and (int(mask_octets[0]) in masks) and (int(mask_octets[1]) in masks) and (int(mask_octets[2]) in masks) and (int(mask_octets[3]) in masks) and (int(mask_octets[0]) >= int(mask_octets[1]) >= int(mask_octets[2]) >= int(mask_octets[3])):breakelse:print("n不是有效的子网掩码,请重新输入n")continuemask_octets_binary = []for octet in mask_octets:binary_octet = bin(int(octet)).lstrip('0b')#print(binary_octet)mask_octets_binary.append(binary_octet.zfill(8))#print(mask_octets_binary)binary_mask = "".join(mask_octets_binary)#print(decimal_mask)no_of_zeros = binary_mask.count("0")no_of_ones = 32 - no_of_zerosno_of_hosts = abs(2 ** no_of_zeros - 2) #当掩码为/32时,2的0次方减1等于-1,需要用abs()函数将其转换成正数1.#print(no_of_zeros)#print(no_of_ones)#print(no_of_hosts)wildcard_octets = []for octet in mask_octets:wild_octet = 255 - int(octet)wildcard_octets.append(str(wild_octet))#print(wildcard_octets)wildcard_mask = ".".join(wildcard_octets)#print(wildcard_mask)ip_octets_binary = []for octet in ip_octets:binary_octet = bin(int(octet)).lstrip('0b')#print(binary_octet)ip_octets_binary.append(binary_octet.zfill(8))#print(ip_octets_binary)binary_ip = "".join(ip_octets_binary)#print(binary_ip)network_address_binary = binary_ip[:(no_of_ones)] + "0" * no_of_zeros#print(network_address_binary)broadcast_address_binary = binary_ip[:(no_of_ones)] + "1" * no_of_zeros#print(broadcast_address_binary)net_ip_octets = []for bit in range(0, 32, 8):net_ip_octet = network_address_binary[bit: bit + 8]net_ip_octets.append(net_ip_octet)#print(net_ip_octets)net_ip_address = []for each_octet in net_ip_octets:net_ip_address.append(str(int(each_octet, 2)))#print(net_ip_address)network_address = ".".join(net_ip_address)#print(network_address)bst_ip_octets = []for bit in range(0, 32, 8):bst_ip_octet = broadcast_address_binary[bit: bit + 8]bst_ip_octets.append(bst_ip_octet)#print(bst_ip_octets)bst_ip_address = []for each_octet in bst_ip_octets:bst_ip_address.append(str(int(each_octet, 2)))#print(bst_ip_address)broadcast_address = ".".join(bst_ip_address)#print(broadcast_address)print("n")print("该网段的网络地址为: %s" % network_address)print("该网段的广播地址为: %s" % broadcast_address)print("该网段可用的IP地址数量为: %s" % no_of_hosts)print("反掩码: %s" % wildcard_mask)print("掩码位: %s" % no_of_ones)print("n")print(input())except KeyboardInterrupt:print("nn程序终止n")sys.exit()


推荐阅读