社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python"ipaddress" 模块之概述

Python程序员 • 6 年前 • 540 次点击  

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。


在本文中,我们会看一看Python 3.3及更高版本中提供的ipaddress模块。 本教程旨在为想知道如何在Python中解析和使用IP地址的网络工程师们提供一个简要参考。

在这篇概述中,你将了解到:

  • IPv4和IPv6地址之间的区别是什么

  • 如何使用Python的ipaddress模块处理IPv4地址

  • 如何使用Python的ipaddress模块处理IPv6地址

IPv4与IPv6地址 - 入门知识

从大的方面来说,IPv4地址和IPv6地址具有相同的目的和功能。但是,由于每个协议的地址结构存在很大差异。本教程用了不同的部分,来分别讨论IPv4和IPv6。

当今的互联网中,IPv4协议承担了绝大部分的IP处理任务,在不久的将来也依旧如此。 尽管IPv6所带来的规模和功能方面的增强对未来互联网不可或缺,正在被逐步应用,但是到目前为止,应用率仍然很低。

一个IPv4地址由32位组成,分为四个“八位组”。 “八位组”一词用于标识一个八位结构来代替更常见的术语“字节”,但它们的定义相同。四个八位组被称为octet1,octet2,octet3和octet4。这是一个“点分十进制”格式,其中每个八位组对应一个从0到255的十进制值。

IPv4地址示例:192.168.100.10

IPv4地址示例(CIDR表示法):192.168.100.10/24

“/24”是CIDR表示法,表示32位的前24位用于标识地址的网络部分。 记住每个八位组长度为8位,这意味着前三个字节(3×8 = 24)标识网络(192.168.100.x),地址的其余八位标识节点(x.x.x.10)。

CIDR表示法可以是从 /8位 到 /30位的任何值,偶尔有 /32位(/31无效),但通常使用/24。 例如,你的家庭网络,或你的学校或公司网络很可能用/24 CIDR来表示。

用于表示网络标识的早期术语是子网掩码,其中CIDR表示为单独的点分十进制数。 例如,一个/24 CIDR相当于一个网络掩码255.255.255.0。

IPv6地址长度为128位,与IPv4地址中的32位相比,有显著的增加。 IPv4和IPv6之间有很多不同之处,但最大的区别在于寻址结构。 额外的长度提供了可支持的网络和主机数量的指数级增长。

IPv6地址示例:2001:db8:abcd:100::1/64

在IPv4地址使用点分十进制格式的情况下,IPv6协议使用十六进制表示法。 IPv6地址中的每个位置表示4个位,其值从0到f,按以下方式组织:

  • 128位被分成8组,每组16位,每组由冒号分隔。一个组被称为4个十六进制字符(4个十六进制字符乘以4位= 16位)的“四重组”或“十六位组”。在上面的例子中,第一个四重组是“2001”。

  • 任何四重组中的头部的0会被去除/压缩。在上面的例子中,第二个四重组是“db8”,实际上是“0db8”“,最开头的0被去掉了。最后一个四重组是“1”,实际上是“0001”“,三个头部0被压缩了。

  • 如果一个四重组包含全零,它将被压缩为一个零。例如:具有“:0000:”的四重组将被压缩为“:0:”。

  • 如果一个地址包含一个连续的全部为零的四重组,则连续的零被压缩并用双冒号表示。在上面的例子中,双冒号表示3个全部为零的四重组,或者“:0000:0000:0000:”浓缩为“::”。由于范例的地址有5个有值的四重组,所以压缩以后的四重组的数量肯定是3个(总数减8)。

所有的IPv6地址结构都使用CIDR表示法来确定有多少前导位用于网络标识,其余部分则用于主机/接口标识。考虑到是128位,产生的组合有很多。

Python的ipaddress模块和IPv4地址

ipaddress模块是按照CIDR表示法设计的,由于其简洁易用,受到人们的推荐。 ipaddress模块还包含了一些方法,用于在必要的情况下还原子网掩码。

IPv4地址的最初定义中包含一个“类”,这个“类”由第一个八位组中的地址范围所定义。 ipaddress模块不识别IPv4类,故在本教程中不会涉及。

ipaddress模块包含三个特定的IPv4地址对象类型:

  • 一个“主机”,或一个不包含CIDR表示法的独立的地址对象

  • 包含CIDR表示法的单个接口地址对象

  • 以及一个网络地址对象,指的是整个网络的IP地址范围。

“主机”和“接口”之间的主要区别在于主机或ip_address对象不包含CIDR表示法,而ip_interface对象包含CIDR表示法:

  • 处理不需要或不使用CIDR表示法的IP数据包时,ip_address对象最为有用。

  • 当使用节点和接口标识来连接到必须包含网络/子网标识的IP网络时,ip_interface对象最管用。

  • ip_network对象包含网络中的所有地址,并且对于网络标识非常有用。

用ipaddress创建IPv4主机地址对象

ipaddress.ip_address() 工厂函数用于创建ip_address对象。它会根据传入的值自动确定是创建IPv4还是IPv6地址(IPv6地址将在本教程的后面部分讨论)。 如上所述,这个对象表示一个数据包在穿越不需要CIDR的网络的过程中,所发现的IP地址。

在多数情况下,用于创建ip_address对象的值将是一个字符串,格式为IPv4点分十进制,如图所示:

或者,IPv4地址可以以二进制形式输入,如完整32位二进制值的十进制值,或按照此例,以十六进制格式输入:

第一个例子使用完整的32位地址,第二个例子是32位地址的十进制值。 两者都很笨拙,容易出错且没什么太大的价值。 第三个示例使用十六进制值,这可能很有用,因为解析或嗅探中的大多数数据包,都以十六进制格式表示。

用ipaddress创建IPv4接口地址对象

ipaddress.ip_interface() 工厂函数用于创建ip_interface对象,该对象根据传入的值自动确定是创建IPv4还是IPv6地址(IPv6地址将在本教程的后面部分讨论)。

如前所述,ip_interface对象表示在正确处理数据包所需的CIDR(或掩码)所在的主机或网络接口上找到的IP地址。

在创建ip_interface选项时可以使用与ip_address选项(二进制,十进制值,十六进制)相同的选项。 但是,唯一通过CIDR表示法或掩码来有效创建ip_interface的办法,是使用点分十进制IPv4地址字符串。

用ipaddress创建IPv4网络地址对象

ipaddress.ip_network()工厂函数用于创建ip_network对象,该对象根据传入的值自动确定是创建IPv4还是IPv6地址(IPv6地址将在本教程的后面部分讨论)。

IP网络定义:包括了一个网络或子网的连续IP地址范围。 例如:

  • 192.168.100.0/24是192.168.100.0网络,其中/24指定前3个八位组组构成网络标识。

  • 第4个八位组用于分配给各个主机和路由器接口。

  • 地址范围是192.168.100.1到.254。

  • 192.168.100.0用于定义网络/子网,192.168.100.255是该网络的广播地址。 它们都不能用于分配给主机或路由器接口。

创建ip_network对象遵循与创建ip_interface对象相同的语法:

在上面的例子中,使用的网络地址必须是一个有效的网络地址,它是构成网络的IPv4地址范围中的第一个地址。 否则,Python将抛出一个异常:

在使用主机或路由器接口时,通常需要确定网络地址。 可以经由计算得出,但是需要几个步骤,可以使用strict = False选项(strict = True是默认值)在一个步骤中完成。

在上面的例子中,ip_interface地址是已知的(192.168.100.10),但不是接口所属的ip_network。 使用strict = False选项,计算ip_network地址(192.168.100.0/24)并将其填充到ip_network对象中。

Python的ipaddress模块和IPv6地址

与IPv4一样,ipaddress模块使用与IPv4相同的三种基本工厂功能。 包括:

  1. 一个“主机”,或一个不包含CIDR表示法的独立地址对象,

  2. 包含CIDR表示法的接口地址对象

  3. 以及引用整个网络的IP地址范围的网络地址对象。

由于详细信息在IPv4部分中已经介绍,在此仅作简要描述。

用ipaddress创建IPv6主机地址对象

ipaddress.ip_address() 工厂函数用于创建ip_address对象。 它会根据传入的值自动确定使用IPv6地址格式。 请注意,CIDR表示法未与ip_address函数一起使用。

在大多数情况下,用于为IPv6创建ip_address对象的值将是根据此示例的IPv6四进制/六进制格式的字符串:

与IPv4一样,可以使用完整的二进制,十进制或十六进制值创建IPv6地址对象。 对于IPv4地址,32位难以处理,而对于128位IPv6地址来说更是尴尬。 实际上,预计八个四重组表示的字符串将是一般形式。

用ipaddress创建IPv6接口地址对象

ipaddress.ip_interface() 工厂函数用于创建ip_interface对象,该对象根据传入的值自动创建IPv6地址。 请注意,函数中必须包含CIDR表示法。

用ipaddress创建IPv6网络地址对象

ipaddress.ip_network() 工厂函数用于根据传入的值为IPv6创建一个ip_network对象。

与IPv4一样,IPv6网络被定义为可分配给特定主机或路由器接口的一系列连续IP地址。

使用我们以前的示例2001:db8:abcd:100:: /64,/64 CIDR指定四个四重组构成完整的网络标识。 请记住,前三个四重组是IPS分配的全局ID,第四个四重组识别内部子网编号。 64位的余额用于从“0000:0000:0000:0001”到“ffff:ffff:ffff:fffe”的范围内的主机标识。

与IPv4寻址一样,IPv6子网中的第一个和最后一个地址不能用于主机寻址。 给定一个/ 64 CIDR,这意味着有2到2的64次方(减2)可能的主机地址,这意味着从数学角度,每个网络/子网有18,446,744,073,709,551,614个可能的主机地址。

上述全局地址分配如下:

  • 全局标识符由ISP分配:2001:db8:abcd::/48

  • 子网标识:2001:db8:abcd:100:: / 64

  • 子网中的第一个可用地址:2001:db8:abcd:100:: 1/64

  • 子网中最后一个可用地址:2001:db8:abcd:100:ffff:ffff:ffff:fffeffff / 64

更多资源

这里是一些额外的资源,以便你进一步了解Python中的ipaddress模块:

本文的扩展PDF版本以及其他信息https://dbader.org/static/img/ipaddress-module-introduction.pdf 

ipaddress模块文档https://docs.python.org/3/library/ipaddress.html 

ipaddress模块介绍https://docs.python.org/3/howto/ipaddress.html 

维基百科 - IPv4https://en.wikipedia.org/wiki/IPv4 

维基百科 - IPv6https://en.wikipedia.org/wiki/IPv6


英文原文:https://dbader.org/blog/python-ipaddress-module
译者:泰然



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/IaBKSXc3Zz
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/11465
 
540 次点击