百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

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

off999 2024-10-30 03:07 28 浏览 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地址和子网掩码是否合法的部分,我已经在相应位置做了备注帮助大家理解,这里就不再赘述了。

最后运行该程序看效果:

相关推荐

大文件传不动?WinRAR/7-Zip 入门到高手,这 5 个技巧让你效率翻倍

“这200张照片怎么传给女儿?微信发不了,邮箱附件又超限……”62岁的张阿姨对着电脑犯愁时,儿子只用了3分钟就把照片压缩成一个文件,还教她:“以后用压缩软件,比打包行李还方便!”职场人更懂这...

电脑解压缩软件推荐——7-Zip:免费、高效、简洁的文件管理神器

在日常工作中,我们经常需要处理压缩文件。无论是下载软件包、接收文件,还是存储大量数据,压缩和解压缩文件都成为了我们日常操作的一部分。而说到压缩解压软件,7-Zip绝对是一个不可忽视的名字。今天,我就来...

设置了加密密码zip文件要如何打开?这几个方法可以试试~

Zip是一种常见的压缩格式文件,文件还可以设置密码保护。那设置了密码的Zip文件要如何打开呢?不清楚的小伙伴一起来看看吧。当我们知道密码想要打开带密码的Zip文件,我们需要用到适用于Zip格式的解压缩...

大文件想要传输成功,怎么把ZIP文件分卷压缩

不知道各位小伙伴有没有这样的烦恼,发送很大很大的压缩包会受到限制,为此,想要在压缩过程中将文件拆分为几个压缩包并且同时为所有压缩包设置加密应该如何设置?方法一:使用7-Zip免费且强大的文件管理工具7...

高效处理 RAR 分卷压缩包:合并解压操作全攻略

在文件传输和存储过程中,当遇到大文件时,我们常常会使用分卷压缩的方式将其拆分成多个较小的压缩包,方便存储和传输。RAR作为一种常见的压缩格式,分卷压缩包的使用频率也很高。但很多人在拿到RAR分卷...

2个方法教你如何删除ZIP压缩包密码

zip压缩包设置了加密密码,每次解压文件都需要输入密码才能够顺利解压出文件,当压缩包文件不再需要加密的时候,大家肯定想删除压缩包密码,或是忘记了压缩包密码,想要通过删除操作将压缩包密码删除,就能够顺利...

速转!漏洞预警丨压缩软件Winrar目录穿越漏洞

WinRAR是一款功能强大的压缩包管理器,它是档案工具RAR在Windows环境下的图形界面。该软件可用于备份数据,缩减电子邮件附件的大小,解压缩从Internet上下载的RAR、ZIP及其它类...

文件解压方法和工具分享_文件解压工具下载

压缩文件减少文件大小,降低文件失效的概率,总得来说好处很多。所以很多文件我们下载下来都是压缩软件,很多小伙伴不知道怎么解压,或者不知道什么工具更好,所以今天做了文件解压方法和工具的分享给大家。一、解压...

[python]《Python编程快速上手:让繁琐工作自动化》学习笔记3

1.组织文件笔记(第9章)(代码下载)1.1文件与文件路径通过importshutil调用shutil模块操作目录,shutil模块能够在Python程序中实现文件复制、移动、改名和删除;同时...

Python内置tarfile模块:读写 tar 归档文件详解

一、学习目标1.1学习目标掌握Python内置模块tarfile的核心功能,包括:理解tar归档文件的原理与常见压缩格式(gzip/bz2/lzma)掌握tar文件的读写操作(创建、解压、查看、过滤...

使用python展开tar包_python拓展

类Unix的系统,打包文件经常使用的就是tar包,结合zip工具,可以方便的打包并解压。在python的标准库里面有tarfile库,可以方便实现生成了展开tar包。使用这个库最大的好处,可能就在于不...

银狐钓鱼再升级:白文件脚本化实现GO语言后门持久驻留

近期,火绒威胁情报中心监测到一批相对更为活跃的“银狐”系列变种木马。火绒安全工程师第一时间获取样本并进行分析。分析发现,该样本通过阿里云存储桶下发恶意文件,采用AppDomainManager进行白利...

ZIP文件怎么打开?2个简单方法教你轻松搞定!

在日常工作和生活中,我们经常会遇到各种压缩文件,其中最常见的格式之一就是ZIP。ZIP文件通过压缩数据来减少文件大小,方便我们进行存储和传输。然而,对于初学者来说,如何打开ZIP文件可能会成为一个小小...

Ubuntu—解压多个zip压缩文件.zip .z01 .z02

方法将所有zip文件放在同一目录中:zip_file.z01,zip_file.z02,zip_file.z03,...,zip_file.zip。在Zip3.0版本及以上,使用下列命令:将所有zi...

如何使用7-Zip对文件进行加密压缩

7-Zip是一款开源的文件归档工具,支持多种压缩格式,并提供了对压缩文件进行加密的功能。使用7-Zip可以轻松创建和解压.7z、.zip等格式的压缩文件,并且可以通过设置密码来保护压缩包中的...

取消回复欢迎 发表评论: