加载中...

11.4 通过CIDR地址生成对应的IP地址集


问题

你有一个CIDR网络地址比如“123.45.67.89/27”,你想将其转换成它所代表的所有IP (比如,“123.45.67.64”, “123.45.67.65”, …, “123.45.67.95”))

解决方案

可以使用 <span class="pre" style="box-sizing: border-box;">ipaddress</span> 模块很容易的实现这样的计算。例如:

  1. >>> import ipaddress
  2. >>> net = ipaddress.ip_network('123.45.67.64/27')
  3. >>> net
  4. IPv4Network('123.45.67.64/27')
  5. >>> for a in net:
  6. ... print(a)
  7. ...
  8. 123.45.67.64
  9. 123.45.67.65
  10. 123.45.67.66
  11. 123.45.67.67
  12. 123.45.67.68
  13. ...
  14. 123.45.67.95
  15. >>>
  16. >>> net6 = ipaddress.ip_network('12:3456:78:90ab:cd:ef01:23:30/125')
  17. >>> net6
  18. IPv6Network('12:3456:78:90ab:cd:ef01:23:30/125')
  19. >>> for a in net6:
  20. ... print(a)
  21. ...
  22. 12:3456:78:90ab:cd:ef01:23:30
  23. 12:3456:78:90ab:cd:ef01:23:31
  24. 12:3456:78:90ab:cd:ef01:23:32
  25. 12:3456:78:90ab:cd:ef01:23:33
  26. 12:3456:78:90ab:cd:ef01:23:34
  27. 12:3456:78:90ab:cd:ef01:23:35
  28. 12:3456:78:90ab:cd:ef01:23:36
  29. 12:3456:78:90ab:cd:ef01:23:37
  30. >>>

<span class="pre" style="box-sizing: border-box;">Network</span> 也允许像数组一样的索引取值,例如:

  1. >>> net.num_addresses
  2. 32
  3. >>> net[0]
  4. IPv4Address('123.45.67.64')
  5. >>> net[1]
  6. IPv4Address('123.45.67.65')
  7. >>> net[-1]
  8. IPv4Address('123.45.67.95')
  9. >>> net[-2]
  10. IPv4Address('123.45.67.94')
  11. >>>

另外,你还可以执行网络成员检查之类的操作:

  1. >>> a = ipaddress.ip_address('123.45.67.69')
  2. >>> a in net
  3. True
  4. >>> b = ipaddress.ip_address('123.45.67.123')
  5. >>> b in net
  6. False
  7. >>>

一个IP地址和网络地址能通过一个IP接口来指定,例如:

  1. >>> inet = ipaddress.ip_interface('123.45.67.73/27')
  2. >>> inet.network
  3. IPv4Network('123.45.67.64/27')
  4. >>> inet.ip
  5. IPv4Address('123.45.67.73')
  6. >>>

讨论

<span class="pre" style="box-sizing: border-box;">ipaddress</span> 模块有很多类可以表示IP地址、网络和接口。 当你需要操作网络地址(比如解析、打印、验证等)的时候会很有用。

要注意的是,<span class="pre" style="box-sizing: border-box;">ipaddress</span> 模块跟其他一些和网络相关的模块比如 <span class="pre" style="box-sizing: border-box;">socket</span> 库交集很少。 所以,你不能使用 <span class="pre" style="box-sizing: border-box;">IPv4Address</span> 的实例来代替一个地址字符串,你首先得显式的使用 <span class="pre" style="box-sizing: border-box;">str()</span> 转换它。例如:

  1. >>> a = ipaddress.ip_address('127.0.0.1')
  2. >>> from socket import socket, AF_INET, SOCK_STREAM
  3. >>> s = socket(AF_INET, SOCK_STREAM)
  4. >>> s.connect((a, 8080))
  5. Traceback (most recent call last):
  6. File "<stdin>", line 1, in <module>
  7. TypeError: Can't convert 'IPv4Address' object to str implicitly
  8. >>> s.connect((str(a), 8080))
  9. >>>

更多相关内容,请参考 An Introduction to the ipaddress Module


还没有评论.