【问题标题】:Calculate netmask from list of IP's从 IP 列表计算网络掩码
【发布时间】:2020-07-14 13:35:46
【问题描述】:

我有一个 IPv4 地址列表,它们都在同一个网络上。我想根据 IP 列表计算该网络的网络掩码。

列表:

192.168.2.2
192.168.2.3
192.168.2.4

生成的网络掩码:255.255.255.0

当前算法:如果八位字节不同,则在该网络掩码位置放置 0,否则放置 255

prev_ip = None
current_netmask = [255,255,255,255]
for ip in ip_list:
  if prev_ip != None:
    for i in range(0,4):
      if ip.split('.')[i] != prev_ip.split('.')[i]:
        current_netmask[i] = 0
  prev_ip = ip    

我的问题是这个网络掩码并不总是正确的,而且我知道其他网络掩码是可能的(除了由 0 和 255 组成的网络掩码)

【问题讨论】:

  • 这不是这三个地址的最长掩码。正确答案是255.255.255.248。试图在文本中操纵 IP 地址是愚蠢的游戏。 IPv4 地址是 32 位无符号整数,您需要计算一下。 this two-part answer 中有一个部分解释了如何做到这一点。

标签: python math networking


【解决方案1】:

我认为这会奏效。将地址转换为整数,以全 1 的掩码开始,并且将从最低有效位开始逐渐为零增加的位,而当 IP 与掩码按位与 -ed 时会有所不同。 (每个新 IP 只需与已考虑的 IP 之一进行比较,因为在那个阶段,掩码已经反映了与所考虑的其他 IP 的比较,因此与 vals[0] 一致。)最后它将掩码转换回点四边形表示。

def to_int(ip):
    bytes = [int(s) for s in ip.split(".")]
    return sum(val<<(8*i) for i, val in enumerate(reversed(bytes)))

def from_int(val):
    r = []
    while val:
        r.append(val & 0xFF)
        val >>= 8
    if len(r) < 4:
        r.extend([0] * (4-len(r)))
    return ".".join(map(str, reversed(r)))

def get_mask(ips):
    vals = [to_int(ip) for ip in ips]
    mask = 0xFFFFFFFF
    bit = 1
    for val in vals[1:]:
        while vals[0] & mask != val & mask:
            mask &= ~bit
            bit <<= 1
    return from_int(mask)

ips = ["192.168.2.2", "192.168.2.3", "192.168.2.4"]
print(get_mask(ips))

给予:

255.255.255.248

【讨论】:

  • ipaddress 包可能有一个更简洁的解决方案,但老实说,从头开始编写东西比学习如何使用它更快。也许其他人可以按照这些思路提供另一个答案。
  • @AnnZen 右移位赋值val &gt;&gt;= 8 等价于val //= 2**8(至少对于正数)
猜你喜欢
  • 2013-11-15
  • 2021-05-20
  • 1970-01-01
  • 2014-10-26
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 2013-03-03
相关资源
最近更新 更多