当前位置:  开发笔记 > 编程语言 > 正文

如何在Python中检查ip是否在网络中?

如何解决《如何在Python中检查ip是否在网络中?》经验,为你挑选了8个好方法。

给定一个IP地址(比如192.168.0.1),如何在Python中检查它是否在网络中(比如192.168.0.0/24)?

Python中是否有用于ip地址操作的通用工具?像主机查找,ip adddress到int,网络地址与netmask到int等等?希望在2.5的标准Python库中.



1> nosklo..:

我喜欢使用netaddr:

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "Yay!"

正如arno_v在评论中指出的那样,netaddr的新版本是这样的:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "Yay!"


或者在新版本中:来自netaddr import IPNetwork,IPNetwork中的IPAddress IPAddress("192.168.0.1")("192.168.0.0/24")

2> phihag..:

使用ipaddress(在3.3以后的stdlib中,在PyPi中为2.6/2.7):

>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True

如果你想以这种方式评估很多 IP地址,你可能想要预先计算网络掩码,比如

n = ipaddress.ip_network('192.0.0.0/16')
netw = int(n.network_address)
mask = int(n.netmask)

然后,对于每个地址,用其中一个计算二进制表示

a = int(ipaddress.ip_address('192.0.43.10'))
a = struct.unpack('!I', socket.inet_pton(socket.AF_INET, '192.0.43.10'))[0]
a = struct.unpack('!I', socket.inet_aton('192.0.43.10'))[0]  # IPv4 only

最后,您只需检查:

in_network = (a & mask) == netw


请注意,python-ipaddr对我们来说表现得相当慢,所以它可能*不适合某些经常需要大量比较的情况.YMMV,所以自己做基准.

3> Dave Webb..:

本文展示了您可以使用socketstruct模块完成它而无需太多额外的工作.我在文章中加了一点如下:

import socket,struct

def makeMask(n):
    "return a mask of n bits as a long integer"
    return (2L<

这输出:

False
True

如果你只想要一个带字符串的函数,它将如下所示:

import socket,struct

def addressInNetwork(ip,net):
   "Is an address in a network"
   ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
   netaddr,bits = net.split('/')
   netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<


注意:这个解决方案有一个严重的错误:`addressInNetwork('172.7.1.1','172.3.0.0/16') - > True`
我认为你的解决方案有一个严重的错误:`addressInNetwork('172.7.1.1','172.3.0.0/16') - > True`(我在我的64位操作系统中将'L'转换为'此外,struct.unpack('L',socket.inet_aton(ip))[0]将在体系结构上失败,其中'L'解包为不同于4字节的内容,而不管字节顺序如何.
继续Rafal的评论,为了让它在64位Python解释器上工作,用以下命令替换该行:`return struct.unpack('我想这里可能存在大的和小的端点问题,但由于网络和IP地址解析都发生在同一台计算机上,因此这两个数字应该具有相同的错误,并且至少在相同的字节顺序中.
请注意,这不适用于IPv6地址.
这个答案有一个*bug*.见答案:http://stackoverflow.com/questions/819355/how-can-i-check-if-an-ip-is-in-a-network-in-python/23230273#23230273
AFAIK inet_aton默认为网络字节顺序,这是大端.事实上,你的代码依赖于inet_aton,它具有与系统1相反的字节序*,因此ip地址的第一个字节(例如"10.0.0.0"中的10)与掩码的最低有效字节对齐(例如0x000000ff中的0xff) .

4> okwap..:

对于python3

In [64]: ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/24')
Out[64]: False



5> Sean Reifsch..:

这段代码在Linux x86上适用于我.我没有真正考虑过endianess问题,但我已经针对"ipaddr"模块测试了它,使用针对8个不同网络字符串测试的超过200K IP地址,并且ipaddr的结果与此代码相同.

def addressInNetwork(ip, net):
   import socket,struct
   ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
   netstr, bits = net.split('/')
   netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
   mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
   return (ipaddr & mask) == (netaddr & mask)

例:

>>> print addressInNetwork('10.9.8.7', '10.9.1.0/16')
True
>>> print addressInNetwork('10.9.8.7', '10.9.1.0/24')
False



6> 小智..:

我尝试过Dave Webb的解决方案,但遇到了一些问题:

最根本的是 - 应通过使用掩码对IP地址进行AND运算来检查匹配,然后检查结果与网络地址完全匹配.没有使用网络地址与IP地址进行AND运算.

我还注意到,只是忽略Endian行为,假设一致性将保存您将只适用于八位字节边界(/ 24,/ 16)上的掩码.为了使其他掩码(/ 23,/ 21)正常工作,我在struct命令中添加了"大于",并将创建二进制掩码的代码更改为以"1"开头并向左移动(32-mask) ).

最后,我添加了一个简单的检查,网络地址对掩码有效,如果不是则只打印警告.

这是结果:

def addressInNetwork(ip,net):
    "Is an address in a network"
    ipaddr = struct.unpack('>L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('>L',socket.inet_aton(netaddr))[0]
    ipaddr_masked = ipaddr & (4294967295<<(32-int(bits)))   # Logical AND of IP address and mask will equal the network address if it matches
    if netmask == netmask & (4294967295<<(32-int(bits))):   # Validate network address is valid for mask
            return ipaddr_masked == netmask
    else:
            print "***WARNING*** Network",netaddr,"not valid with mask /"+bits
            return ipaddr_masked == netmask



7> Landon..:

我不喜欢在不需要时使用模块.这项工作只需要简单的数学,所以这是我完成这项工作的简单功能:

def ipToInt(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res

def isIpInSubnet(ip, ipNetwork, maskLength):
    ipInt = ipToInt(ip)#my test ip, in int form

    maskLengthFromRight = 32 - maskLength

    ipNetworkInt = ipToInt(ipNetwork) #convert the ip network into integer form
    binString = "{0:b}".format(ipNetworkInt) #convert that into into binary (string format)

    chopAmount = 0 #find out how much of that int I need to cut off
    for i in range(maskLengthFromRight):
        if i < len(binString):
            chopAmount += int(binString[len(binString)-1-i]) * 2**i

    minVal = ipNetworkInt-chopAmount
    maxVal = minVal+2**maskLengthFromRight -1

    return minVal <= ipInt and ipInt <= maxVal

然后使用它:

>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',24) 
True
>>> print isIpInSubnet('66.151.97.193', '66.151.97.192',29) 
True
>>> print isIpInSubnet('66.151.96.0', '66.151.97.192',24) 
False
>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',29) 

就是这样,这比包含模块的上述解决方案快得多.



8> 小智..:

接受的答案不起作用......这让我很生气.掩码是向后的,不适用于任何不是简单8位块的位(例如/ 24).我调整了答案,并且效果很好.

    import socket,struct

    def addressInNetwork(ip, net_n_bits):  
      ipaddr = struct.unpack('!L', socket.inet_aton(ip))[0]
      net, bits = net_n_bits.split('/')
      netaddr = struct.unpack('!L', socket.inet_aton(net))[0]
      netmask = (0xFFFFFFFF >> int(bits)) ^ 0xFFFFFFFF
      return ipaddr & netmask == netaddr

这是一个返回虚线二进制字符串的函数,以帮助可视化屏蔽......有点像ipcalc输出.

    def bb(i):
     def s = '{:032b}'.format(i)
     def return s[0:8]+"."+s[8:16]+"."+s[16:24]+"."+s[24:32]

例如:

屏幕截图的蟒蛇

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有