您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

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

时间:2020-09-14 13:08:56  来源:  作者:

今天从Python/ target=_blank class=infotextkey>Python的角度来聊下计算机网络这行基础中的基础的话题:网络和IP地址计算(注:本文里的IP指的是IPv4,不涉及IPv6)。相信几乎每位网工读者在平时的工作和学习中都用过类似下图的在线网络和IP地址计算器吧:

用Python开发一个交互式网络和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中实现的方法如下:

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

 

  • 这里我们用字符串自带的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')将其拿掉,演示如下:
用Python开发一个交互式网络和IP地址计算器

 

  • 再来看ip_octets_binary.Append(binary_octet.zfill(8))中的zfill(8),它的作用是自动帮我们填充八位数的二进制数,什么意思呢?比如我们有个IP地址192.168.0.1,它的第三个八位组为0,写成二进制的话应该为00000000,如果我们将0用bin()转换成二进制后会怎么样呢?演示如下:
用Python开发一个交互式网络和IP地址计算器

 

是不是只得到了一位数的二进制数0?加上zfill(8)后即得到八位组的二进制00000000,效果如下:

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

 

同样的代码也适用于子网掩码,比如在Python中要将255.255.255.0这个掩码转换成二进制形式,代码可以这么写:

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

 

B.

知道如何在Python里将十进制的IP地址和子网掩码转换成二进制后,我们再来看下如何将二进制的IP地址和子网掩码转换回十进制(代码接续前文):

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

 

  • 这里只讲一点,在Python中我们可以借助int()函数里的2这个参数将数据类型为字符串的二进制数字转换成数据类型为整数的十进制数字,举例如下:
用Python开发一个交互式网络和IP地址计算器

 

  • 同样的道理,我们可以将二进制形式的子网掩码转换回十进制:
用Python开发一个交互式网络和IP地址计算器

 

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中的计算方式如下(代码接前文):

用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-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("nn程序终止n")
    sys.exit()
  • 代码前面用来判断用户所输入的IP地址和子网掩码是否合法的部分,我已经在相应位置做了备注帮助大家理解,这里就不再赘述了。

最后运行该程序看效果:

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

 


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

 


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

 



Tags:IP地址   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
首先我们来看看以下这两个地址是否可以相互通信呢? 初步一看,貌似可以通信,但是再细看,发现两者的掩码完全不同,故而肯定不能通信了?然而并非如此,如果对两者的通信有更深刻的认识,...【详细内容】
2022-07-15  Tags: IP地址  点击:(2)  评论:(0)  加入收藏
<script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> <script> console.log(returnCitySN["cip"]+&#39;,&#39;+returnCitySN["cname"]) </script> JS命名空间是...【详细内容】
2022-07-14  Tags: IP地址  点击:(4)  评论:(0)  加入收藏
当用户访问网站时,在浏览器地址栏中输入域名,就能自动转跳到对应的网站,但其实每个网址背后有一个相应的IP地址,因为要用户记住及输入一串数字比较困难,所以衍生一个叫DNS服务器...【详细内容】
2022-07-08  Tags: IP地址  点击:(16)  评论:(0)  加入收藏
很多情况下,你可能需要在Linux下屏蔽IP地址。如果你是一名系统管理员,你可能想要禁止垃圾IP地址访问你们的公司邮件服务器。或者你因一些原因想要禁止某些国家访问你的web服务...【详细内容】
2022-06-29  Tags: IP地址  点击:(25)  评论:(0)  加入收藏
centos7系统下无法dhcp自动获取ip地址问题:VMware WorkStation新建centos7无法DHCP自动获取IP地址。解决方法:在VMware的网络配置NAT正确的情况下,修改vim /etc/sysconfig/netw...【详细内容】
2022-06-01  Tags: IP地址  点击:(52)  评论:(0)  加入收藏
作为互联网民工,我们对虚拟机肯定不陌生,在虚拟机的配置中,有以下几种网络连接模式:其中桥接模式算是用得最多的一种了,一般来说如果想要我们的虚拟机连接外网,我们都是选择桥接模...【详细内容】
2022-05-16  Tags: IP地址  点击:(164)  评论:(0)  加入收藏
附录1:如果你在网上发布动态或者评论之后,IP属地还没有显示,或者是显示错了,不要急着找微信、微博、抖音这些平台的客服。因为他们能知道你在哪个城市...【详细内容】
2022-05-09  Tags: IP地址  点击:(46)  评论:(0)  加入收藏
随着家用宽带的提速降费,现在每个家家户户都装上了宽带,家里的联网设备也随之增多,手机电视机等这类设备一般连接上网络都可以使用,像监控、NSA、外网唤醒之类的对于像我们这类...【详细内容】
2022-04-29  Tags: IP地址  点击:(418)  评论:(0)  加入收藏
我们都知道我们在上网的时候都有一个IP地址,用来和其他人进行通信和数据交换,如果还不知道什么是IP地址的建议看一下我的文章:一分钟了解IP地址,网络真不是法外之地,劝你谨言慎行...【详细内容】
2022-04-24  Tags: IP地址  点击:(111)  评论:(0)  加入收藏
&#39;============================ &#39;函数名称: GetNICInfo &#39;功能描述: 返回由指定分隔符分隔的未被禁用的网卡MAC地址或IP地址,具体的返回内容由Index参数确定。 &#39...【详细内容】
2022-04-11  Tags: IP地址  点击:(66)  评论:(0)  加入收藏
▌简易百科推荐
近几年 Web3 被炒得火热,但是大部分人可能还不清楚什么是 Web3,今天就让w3cschool编程狮小师妹带你了解下 Web3 是什么?与我们熟知的 Web1 和 Web2 又有什么区别呢?web3.0什么是...【详细内容】
2022-07-15  编程狮W3Cschool    Tags:Web3.0   点击:(2)  评论:(0)  加入收藏
1、让我们一起来看下吧,直接上图。 第一眼看到是不是觉得很高逼格,暗黑画风,这很大佬。其实它就是------AidLearning。一个运行在安卓平台的linux系统,而且还包含了许多非常强大...【详细内容】
2022-07-15  IT智能化专栏    Tags:AidLearning   点击:(2)  评论:(0)  加入收藏
真正的大师,永远都怀着一颗学徒的心! 一、项目简介 今天说的这个软件是一款基于Python+vue的自动化运维、完全开源的云管理平台。二、实现功能 基于RBAC权限系统 录像回放 ...【详细内容】
2022-07-14  菜鸟程序猿    Tags:Python   点击:(3)  评论:(0)  加入收藏
前言今天笔者想和大家来聊聊python接口自动化的MySQL数据连接,废话不多说咱们直接进入主题吧。 一、什么是 PyMySQL?PyMySQL是在Python3.x版本中用于连接MySQL服务器的一个库,P...【详细内容】
2022-07-11  测试架构师百里    Tags:python   点击:(19)  评论:(0)  加入收藏
aiohttp什么是 aiohttp?一个异步的 HTTP 客户端\服务端框架,基于 asyncio 的异步模块。可用于实现异步爬虫,更快于 requests 的同步爬虫。安装pip install aiohttpaiohttp 和 r...【详细内容】
2022-07-11  VT漫步    Tags:aiohttp   点击:(15)  评论:(0)  加入收藏
今天我们学习下 Queue 的进阶用法。生产者消费者模型在并发编程中,比如爬虫,有的线程负责爬取数据,有的线程负责对爬取到的数据做处理(清洗、分类和入库)。假如他们是直接交互的,...【详细内容】
2022-07-06  VT漫步    Tags:Python Queue   点击:(34)  评论:(0)  加入收藏
继承:是面向对象编程最重要的特性之一,例如,我们每个人都从祖辈和父母那里继承了一些体貌特征,但每个人却又不同于父母,有自己独有的一些特性。在面向对象中被继承的类是父类或基...【详细内容】
2022-07-06  至尊小狸子    Tags:python   点击:(25)  评论:(0)  加入收藏
点击上方头像关注我,每周上午 09:00准时推送,每月不定期赠送技术书籍。本文1553字,阅读约需4分钟 Hi,大家好,我是CoCo。在上一篇Python自动化测试系列文章:Python自动化测试之P...【详细内容】
2022-07-05  CoCo的软件测试小栈    Tags:Python   点击:(27)  评论:(0)  加入收藏
第一种方式:res = requests.get(url, params=data, headers = headers)第二种方式:res = requests.get(url, data=data, headers = headers)注意:1.url格式入参只支持第一种方...【详细内容】
2022-07-05  独钓寒江雪之IT    Tags:Python request   点击:(19)  评论:(0)  加入收藏
什么是python类的多态python的多态,可以为不同的类实例,或者说不同的数据处理方式,提供统一的接口。用比喻的方式理解python类的多态比如,同一个苹果(统一的接口)在孩子的眼里(类实...【详细内容】
2022-07-04  写小说的程序员    Tags:python类   点击:(28)  评论:(0)  加入收藏
站内最新
站内热门
站内头条