用Python开发一个交互式网络和IP地址计算器
off999 2024-10-30 03:07 49 浏览 0 评论
今天从Python的角度来聊下计算机网络这行基础中的基础的话题:网络和IP地址计算(注:本文里的IP指的是IPv4,不涉及IPv6)。相信几乎每位网工读者在平时的工作和学习中都用过类似下图的在线网络和IP地址计算器吧:
这类前人(或者说码农们)造出的轮子的确很好用,但是很少有网工明白它们背后的工作原理(也就是代码是怎么写出来的)。作为有志成为NetDevOps Engineer的我们有必要深入的从代码的角度来学习一下,不妨自己也用Python从零写一个交互式的网络和IP地址计算器,重新造一遍轮子,一来可以温故知新,二来可以帮助我们更深入的了解二进制和十进制在Python里是怎么玩的。该交互式计算器的作用是让用户输入一个合法的IP地址及子网掩码,然后根据用户输入的信息自动给出用户查询的网段的网络IP、广播IP、网段内可用的IP地址数、反掩码以及用户输入的子网掩码对应的“/”格式的掩码位(比如用户输入的掩码是255.255.128.0,计算器会自动在结果中给出/17的掩码位)。
因为是所有网工必须掌握的基本功,为了节约篇幅,下面我只高度概括一下网络和IP地址计算的理论要点,我们重点要关注的是如何在Python中实现它们(所有演示我都将在解释器里实时完成,让读者更清楚的看到十进制和二进制的相互转换在Python中是怎样完成的)大致可以归纳为A,B,C,D,E总共5个点,分述如下:
A.
我们知道任何一个合法的IP地址和子网掩码都可以用32位的二进制(binary)表示,这32位二进制又被分为4个八位位组(octet),比如192.168.1.1用二进制可以写成11000000.10101000.00000001.00000001,这个转换步骤在Python中实现的方法如下:
- 这里我们用字符串自带的split()函数将ip地址(字符串‘192.168.1.1')转换成列表ip_octets,然后创建一个空列表ip_octets_binary,随后用for循环遍历ip_octets里的元素,将它们每个用bin()函数转换成二进制形式,然后一一写入刚才创建的空列表ip_octets_binary里面。
- 关于binary_octet = bin(int(octet)).lstrip('0b'),bin()只能将数据类型为整数的十进制数转换成二进制,因此这里我们要先将字符串用int()转换成整数后再来调用bin()函数,而bin()函数本身会在转化后的二进制数字前面加上'0b',我们必须调用lstrip('0b')将其拿掉,演示如下:
- 再来看ip_octets_binary.append(binary_octet.zfill(8))中的zfill(8),它的作用是自动帮我们填充八位数的二进制数,什么意思呢?比如我们有个IP地址192.168.0.1,它的第三个八位组为0,写成二进制的话应该为00000000,如果我们将0用bin()转换成二进制后会怎么样呢?演示如下:
是不是只得到了一位数的二进制数0?加上zfill(8)后即得到八位组的二进制00000000,效果如下:
同样的代码也适用于子网掩码,比如在Python中要将255.255.255.0这个掩码转换成二进制形式,代码可以这么写:
B.
知道如何在Python里将十进制的IP地址和子网掩码转换成二进制后,我们再来看下如何将二进制的IP地址和子网掩码转换回十进制(代码接续前文):
- 这里只讲一点,在Python中我们可以借助int()函数里的2这个参数将数据类型为字符串的二进制数字转换成数据类型为整数的十进制数字,举例如下:
- 同样的道理,我们可以将二进制形式的子网掩码转换回十进制:
C.
我们知道要算出一个网段内有多少可用的IP地址需要知道该网段的子网掩码以二进制表达时里面有多少个0 (number of zeros,在Python中我们将其赋值给变量no_of_zeros),然后套用公式2 ** no_of_zeros - 2即可算出,比如这里给定的子网掩码255.255.255.0,将其转化为二进制为1111111.1111111.11111111.00000000,总共8个0, 那么2**8-2 = 254,即为我们要的结果,这个运算过程在Python中的计算方式如下(代码接前文):
- 这里我们用abs()这个绝对值函数来计算有多少可用的IP地址,原因是当子网掩码为/32 (255.255.255.255)时,no_of_zeros = 0,如果不用abs()的话, 2 ** 0 - 2 结果为负1,用abs()则可以将其转换成正1, 演示如下:
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为例):
- 在使用上面提到的填充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
E.
最后我们来谈谈反掩码,所谓反掩码就是将子网掩码的二进制里的1换成0,将0换成1,比如255.255.255.0的二进制为11111111.11111111.11111111.00000000,它的反掩码即为00000000.00000000.00000000.11111111,也就是0.0.0.255。在Python里我们可以这样表示(代码接上文):
最后来看下该交互式的网络和IP地址计算器的最终代码:
#coding=utf-8
import sys
try:
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地址均不是有效的IP
if (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):
break
else:
print("\n不是有效的IP地址,请重新输入\n")
continue
masks = [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])):
break
else:
print("\n不是有效的子网掩码,请重新输入\n")
continue
mask_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_zeros
no_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("\n\n程序终止\n")
sys.exit()- 代码前面用来判断用户所输入的IP地址和子网掩码是否合法的部分,我已经在相应位置做了备注帮助大家理解,这里就不再赘述了。
最后运行该程序看效果:
相关推荐
- 安全教育登录入口平台(安全教育登录入口平台官网)
-
122交通安全教育怎么登录:122交通网的注册方法是首先登录网址http://www.122.cn/,接着打开网页后,点击右上角的“个人登录”;其次进入邮箱注册,然后进入到注册页面,输入相关信息即可完...
- 大鱼吃小鱼经典版(大鱼吃小鱼经典版(经典版)官方版)
-
大鱼吃小鱼小鱼吃虾是于谦跟郭麒麟的《我的棒儿呢?》郭德纲说于思洋郭麒麟作诗的相声,最后郭麒麟做了一首,师傅躺在师母身上大鱼吃小鱼小鱼吃虾虾吃水水落石出师傅压师娘师娘压床床压地地动山摇。...
-
- 哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)
-
要想将ppt免费转换为pdf的话,我们建议大家可以下一个那个wps,如果你是会员的话,可以注册为会员,这样的话,在wps里面的话,就可以免费将ppt呢转换为pdfpdf之后呢,我们就可以直接使用,不需要去直接不需要去另外保存,为什么格式转...
-
2026-02-04 09:03 off999
- 电信宽带测速官网入口(电信宽带测速官网入口app)
-
这个网站看看http://www.swok.cn/pcindex.jsp1.登录中国电信网上营业厅,宽带光纤,贴心服务,宽带测速2.下载第三方软件,如360等。进行在线测速进行宽带测速时,尽...
- 植物大战僵尸95版手机下载(植物大战僵尸95 版下载)
-
1可以在应用商店或者游戏平台上下载植物大战僵尸95版手机游戏。2下载教程:打开应用商店或者游戏平台,搜索“植物大战僵尸95版”,找到游戏后点击下载按钮,等待下载完成即可安装并开始游戏。3注意:确...
- 免费下载ppt成品的网站(ppt成品免费下载的网站有哪些)
-
1、Chuangkit(chuangkit.com)直达地址:chuangkit.com2、Woodo幻灯片(woodo.cn)直达链接:woodo.cn3、OfficePlus(officeplu...
- 2025世界杯赛程表(2025世界杯在哪个国家)
-
2022年卡塔尔世界杯赛程公布,全部比赛在卡塔尔境内8座球场举行,2022年,决赛阶段球队全部确定。揭幕战于当地时间11月20日19时进行,由东道主卡塔尔对阵厄瓜多尔,决赛于当地时间12月18日...
- 下载搜狐视频电视剧(搜狐电视剧下载安装)
-
搜狐视频APP下载好的视频想要导出到手机相册里方法如下1、打开手机搜狐视频软件,进入搜狐视频后我们点击右上角的“查找”,找到自已喜欢的视频。2、在“浏览器页面搜索”窗口中,输入要下载的视频的名称,然后...
- 永久免费听歌网站(丫丫音乐网)
-
可以到《我爱音乐网》《好听音乐网》《一听音乐网》《YYMP3音乐网》还可以到《九天音乐网》永久免费听歌软件有酷狗音乐和天猫精灵,以前要跳舞经常要下载舞曲,我从QQ上找不到舞曲下载就从酷狗音乐上找,大多...
- 音乐格式转换mp3软件(音乐格式转换器免费版)
-
有两种方法:方法一在手机上操作:1、进入手机中的文件管理。2、在其中选择“音乐”,将显示出手机中的全部音乐。3、点击“全选”,选中所有音乐文件。4、点击屏幕右下方的省略号图标,在弹出菜单中选择“...
- 电子书txt下载(免费的最全的小说阅读器)
-
1.Z-library里面收录了近千万本电子书籍,需求量大。2.苦瓜书盘没有广告,不需要账号注册,使用起来非常简单,直接搜索预览下载即可。3.鸠摩搜书整体风格简洁清晰,书籍资源丰富。4.亚马逊图书书籍...
- 最好免费观看高清电影(播放免费的最好看的电影)
-
在目前的网上选择中,IMDb(互联网电影数据库)被认为是最全的电影网站之一。这个网站提供了各种类型的电影和电视节目的海量信息,包括剧情介绍、演员表、评价、评论等。其还提供了有关电影制作背后的详细信息,...
- 孤单枪手2简体中文版(孤单枪手2简体中文版官方下载)
-
要将《孤胆枪手2》游戏的征兵秘籍切换为中文,您可以按照以下步骤进行操作:首先,打开游戏设置选项,通常可以在游戏主菜单或游戏内部找到。然后,寻找语言选项或界面选项,点击进入。在语言选项中,选择中文作为游...
欢迎 你 发表评论:
- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
