كيف يمكنني التحقق مما إذا كان IP في شبكة في بيثون؟

StackOverflow https://stackoverflow.com/questions/819355

سؤال

بالنظر إلى عنوان IP (على سبيل المثال 192.168.0.1) ، كيف يمكنني التحقق مما إذا كان في شبكة (قل 192.168.0.0/24) في بيثون؟

هل هناك أدوات عامة في بيثون لمعالجة عنوان IP؟ أشياء مثل عمليات البحث عن المضيف ، IP AddDress إلى int ، عنوان الشبكة مع Netmask إلى int وما إلى ذلك؟ نأمل في مكتبة بيثون القياسية لمدة 2.5.

هل كانت مفيدة؟

المحلول

هذه المقالة يظهر أنه يمكنك القيام بذلك مع socket و struct وحدات دون الكثير من الجهد الإضافي. أضفت قليلاً إلى المقالة على النحو التالي:

import socket,struct

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

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def networkMask(ip,bits):
    "Convert a network address to a long integer" 
    return dottedQuadToNum(ip) & makeMask(bits)

def addressInNetwork(ip,net):
   "Is an address in a network"
   return ip & net == net

address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)

هذا المخرجات:

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<<int(bits)-1) - 1)
   return ipaddr & netmask == netmask

نصائح أخرى

أحب الاستخدام 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!"

استخدام ipaddress (في stdlib منذ 3.3, في 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 بهذه الطريقة ، ربما تريد حساب Netmask مقدمًا ، مثل

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

هذا الرمز يعمل بالنسبة لي على Linux X86. لم أفكر حقًا في أي مشكلات إنديان ، لكنني اختبرتها ضد وحدة "iPaddr" باستخدام أكثر من 200 ألف عنوان IP تم اختبارها مقابل 8 سلاسل شبكات مختلفة ، ونتائج 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

ل Python3

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

جربت حل ديف ويب ولكن ضربت بعض المشاكل:

الأهم من ذلك - يجب فحص المباراة عن طريق وصلة عنوان IP مع القناع ، ثم التحقق من النتيجة تطابق عنوان الشبكة بالضبط. ليس وينج عنوان IP مع عنوان الشبكة كما حدث.

لاحظت أيضًا أن تجاهل السلوك الإنديان على افتراض أن الاتساق سيوفر لك فقط سيعمل على أقنعة على حدود الثماني ( /24 ، /16). من أجل الحصول على أقنعة أخرى ( /23 ، /21) تعمل بشكل صحيح ، أضفت "أكبر من" إلى أوامر الهيكل وتغيير الكود لإنشاء القناع الثنائي للبدء بكل "1" والتحول اليسار بواسطة (32 قناع ).

أخيرًا ، أضفت التحقق البسيط من أن عنوان الشبكة صالح للقناع وطباعة تحذير فقط إذا لم يكن كذلك.

ها هي النتيجة:

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

أنا لست من محبي استخدام الوحدات النمطية عندما لا تكون هناك حاجة إليها. هذه المهمة تتطلب الرياضيات البسيطة فقط ، لذا إليك وظيفتي البسيطة للقيام بالمهمة:

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 بت (على سبيل المثال /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]

على سبيل المثال:

screen shot of python

ليس في المكتبة القياسية لـ 2.5 ، لكن iPaddr يجعل هذا الأمر سهلاً للغاية. أعتقد أنه في 3.3 تحت اسم ipaddress.

import ipaddr

a = ipaddr.IPAddress('192.168.0.1')
n = ipaddr.IPNetwork('192.168.0.0/24')

#This will return True
n.Contains(a)

رمز مارك صحيح تقريبا. نسخة كاملة من الرمز هي -

def addressInNetwork3(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(int(bits))))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-mask,32):
        bits |= (1 << i)
    return "%d.%d.%d.%d" % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

من الواضح من نفس المصادر على النحو الوارد أعلاه ...

ملاحظة مهمة للغاية هي أن الكود الأول يحتوي على خلل صغير - عنوان IP 255.255.255.255 يظهر أيضًا كـ IP صالح لأي شبكة فرعية. كان لدي وقت من الوقت في الحصول على هذا الرمز للعمل وبفضل مارك على الإجابة الصحيحة.

يمكن أن يسبب الاعتماد على وحدة "الهيكل" مشاكل في أحجام endian-nys و type ، وليس هناك حاجة إليها. ولا socket.inet_aton (). يعمل Python بشكل جيد للغاية مع عناوين IP المنقطة:

def ip_to_u32(ip):
  return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)

أحتاج إلى القيام بمطابقة IP على كل مقبس قبول () ، مقابل مجموعة كاملة من الشبكات المصدر المسموح بها ، لذلك أنا أقنعة وشبكات محسوبة ، كمناسبات: أعداد صحيحة:

SNS_SOURCES = [
  # US-EAST-1
  '207.171.167.101',
  '207.171.167.25',
  '207.171.167.26',
  '207.171.172.6',
  '54.239.98.0/24',
  '54.240.217.16/29',
  '54.240.217.8/29',
  '54.240.217.64/28',
  '54.240.217.80/29',
  '72.21.196.64/29',
  '72.21.198.64/29',
  '72.21.198.72',
  '72.21.217.0/24',
  ]

def build_masks():
  masks = [ ]
  for cidr in SNS_SOURCES:
    if '/' in cidr:
      netstr, bits = cidr.split('/')
      mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
      net = ip_to_u32(netstr) & mask
    else:
      mask = 0xffffffff
      net = ip_to_u32(cidr)
    masks.append((mask, net))
  return masks

ثم يمكنني معرفة ما إذا كان عنوان IP معين ضمن إحدى هذه الشبكات:

ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
  if ip & mask == net:
    # matched!
    break
else:
  raise BadClientIP(ipstr)

لا حاجة للواردات النمطية ، والرمز هو جداً سريع في المطابقة.

من netaddr import all_matching_cidrs

>>> from netaddr import all_matching_cidrs
>>> all_matching_cidrs("212.11.70.34", ["192.168.0.0/24","212.11.64.0/19"] )
[IPNetwork('212.11.64.0/19')]

هنا هو استخدام هذه الطريقة:

>>> help(all_matching_cidrs)

Help on function all_matching_cidrs in module netaddr.ip:

all_matching_cidrs(ip, cidrs)
    Matches an IP address or subnet against a given sequence of IP addresses and subnets.

    @param ip: a single IP address or subnet.

    @param cidrs: a sequence of IP addresses and/or subnets.

    @return: all matching IPAddress and/or IPNetwork objects from the provided
    sequence, an empty list if there was no match.

في الأساس ، يمكنك تقديم عنوان IP كوسيطة أولى وقائمة من CIDRs كوسيطة ثانية. يتم إرجاع قائمة من الزيارات.

#This works properly without the weird byte by byte handling
def addressInNetwork(ip,net):
    '''Is an address in a network'''
    # Convert addresses to host order, so shifts actually make sense
    ip = struct.unpack('>L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netaddr = struct.unpack('>L',socket.inet_aton(netaddr))[0]
    # Must shift left an all ones value, /32 = zero shift, /0 = 32 shift left
    netmask = (0xffffffff << (32-int(bits))) & 0xffffffff
    # There's no need to mask the network address, as long as its a proper network address
    return (ip & netmask) == netaddr 

الإجابة المختارة لها خطأ.

فيما يلي الرمز الصحيح:

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 = ((1L << int(bits)) - 1)
   return ipaddr & netmask == netaddr & netmask

ملحوظة: ipaddr & netmask == netaddr & netmask بدلاً من ipaddr & netmask == netmask.

أنا أيضا استبدال ((2L<<int(bits)-1) - 1) مع ((1L << int(bits)) - 1), ، كما يبدو الأخير أكثر فهمًا.

إليكم الفصل الذي كتبته لأطول بادئة مطابقة:

#!/usr/bin/env python

class Node:
def __init__(self):
    self.left_child = None
    self.right_child = None
    self.data = "-"

def setData(self, data): self.data = data
def setLeft(self, pointer): self.left_child = pointer
def setRight(self, pointer): self.right_child = pointer
def getData(self): return self.data
def getLeft(self): return self.left_child
def getRight(self): return self.right_child

def __str__(self):
        return "LC: %s RC: %s data: %s" % (self.left_child, self.right_child, self.data)


class LPMTrie:      

def __init__(self):
    self.nodes = [Node()]
    self.curr_node_ind = 0

def addPrefix(self, prefix):
    self.curr_node_ind = 0
    prefix_bits = ''.join([bin(int(x)+256)[3:] for x in prefix.split('/')[0].split('.')])
    prefix_length = int(prefix.split('/')[1])
    for i in xrange(0, prefix_length):
        if (prefix_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setRight(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setLeft(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)

        if i == prefix_length - 1 :
            self.nodes[self.curr_node_ind].setData(prefix)

def searchPrefix(self, ip):
    self.curr_node_ind = 0
    ip_bits = ''.join([bin(int(x)+256)[3:] for x in ip.split('.')])
    for i in xrange(0, 32):
        if (ip_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                return self.nodes[self.curr_node_ind].getData()
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                return self.nodes[self.curr_node_ind].getData()

    return None

def triePrint(self):
    n = 1
    for i in self.nodes:
        print n, ':'
        print i
        n += 1

وهنا برنامج اختبار:

n=LPMTrie()
n.addPrefix('10.25.63.0/24')
n.addPrefix('10.25.63.0/16')
n.addPrefix('100.25.63.2/8')
n.addPrefix('100.25.0.3/16')
print n.searchPrefix('10.25.63.152')
print n.searchPrefix('100.25.63.200')
#10.25.63.0/24
#100.25.0.3/16

شكرا لك على البرنامج النصي الخاص بك!
لدي عمل طويل على جعل كل شيء يعمل ... لذلك أنا أشاركه هنا

  • يعد استخدام فئة NetAddr أبطأ 10 مرات من استخدام التحويل الثنائي ، لذلك إذا كنت ترغب في استخدامه في قائمة كبيرة من IP ، فيجب عليك عدم استخدام فئة Netaddr
  • وظيفة makemask لا تعمل! العمل فقط ل/8 ،/16 ،/24
    السابق:

    بت = "21" ؛ socket.inet_ntoa (struct.pack ('= l' ، (2l << int (bits) -1) - 1))
    "255.255.31.0" في حين يجب أن يكون 255.255.248.0

    لذلك استخدمت وظيفة أخرى calcdottednetmask (قناع) من http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
    السابق:


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • مشكلة أخرى هي عملية المطابقة إذا كان عنوان IP ينتمي إلى شبكة! يجب أن تكون العملية الأساسية للمقارنة (iPaddr & netmask) و (الشبكة و Netmask).
    على سبيل المثال: في الوقت الحالي ، فإن الوظيفة خاطئة

#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
>>>True which is completely WRONG!!

لذا فإن وظيفة addringInnetwork الجديدة الخاصة بي تبدو شبيهة:


#!/usr/bin/python
import socket,struct
def addressInNetwork(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(bits)))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-int(mask),32):
        bits |= (1 > 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))


والآن ، الجواب صحيح !!


#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
False

آمل أن يساعد ذلك الآخرين ، وتوفير الوقت لهم!

فيما يتعلق بكل ما سبق ، أعتقد أن socket.inet_aton () يعيد بايت بترتيب الشبكة ، وبالتالي فإن الطريقة الصحيحة لتفريغها هي على الأرجح

struct.unpack('!L', ... )

الحل السابق له خطأ في IP & net == net. بحث IP الصحيح هو IP & netmask = net

رمز bugfixed:

import socket
import struct

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

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def addressInNetwork(ip,net,netmask):
   "Is an address in a network"
   print "IP "+str(ip) + " NET "+str(net) + " MASK "+str(netmask)+" AND "+str(ip & netmask)
   return ip & netmask == net

def humannetcheck(ip,net):
        address=dottedQuadToNum(ip)
        netaddr=dottedQuadToNum(net.split("/")[0])
        netmask=makeMask(long(net.split("/")[1]))
        return addressInNetwork(address,netaddr,netmask)


print humannetcheck("192.168.0.1","192.168.0.0/24");
print humannetcheck("192.169.0.1","192.168.0.0/24");

هناك واجهة برمجة تطبيقات تسمى الشبكات الفرعية المتاحة في بيثون تقوم بهذه المهمة بشكل جيد للغاية. هذا مثال بسيط :

import SubnetTree
t = SubnetTree.SubnetTree()
t.insert("10.0.1.3/32")
print("10.0.1.3" in t)

هذا هو الرابط

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('/')
    netaddr = struct.unpack('!L',socket.inet_aton(netaddr))[0]
    netmask = ((1<<(32-int(bits))) - 1)^0xffffffff
    return ipaddr & netmask == netaddr & netmask
print addressInNetwork('10.10.10.110','10.10.10.128/25')
print addressInNetwork('10.10.10.110','10.10.10.0/25')
print addressInNetwork('10.10.10.110','10.20.10.128/25')

$ python check-subnet.py
خطأ شنيع
حقيقي
خطأ شنيع

لا أعرف أي شيء في المكتبة القياسية ، لكن pysubnettree هي مكتبة Python التي ستقوم بمطابقة الشبكة الفرعية.

من مصادر مختلفة أعلاه ، ومن بحثي الخاص ، هكذا حصلت على الشبكة الفرعية وحساب العنوان. هذه القطع كافية لحل السؤال والأسئلة الأخرى ذات الصلة.

class iptools:
    @staticmethod
    def dottedQuadToNum(ip):
        "convert decimal dotted quad string to long integer"
        return struct.unpack('>L', socket.inet_aton(ip))[0]

    @staticmethod
    def numToDottedQuad(n):
        "convert long int to dotted quad string"
        return socket.inet_ntoa(struct.pack('>L', n))

    @staticmethod
    def makeNetmask(mask):
        bits = 0
        for i in xrange(32-int(mask), 32):
            bits |= (1 << i)
        return bits

    @staticmethod
    def ipToNetAndHost(ip, maskbits):
        "returns tuple (network, host) dotted-quad addresses given"
        " IP and mask size"
        # (by Greg Jorgensen)
        n = iptools.dottedQuadToNum(ip)
        m = iptools.makeMask(maskbits)
        net = n & m
        host = n - mask
        return iptools.numToDottedQuad(net), iptools.numToDottedQuad(host)

ها هو الكود الخاص بي

# -*- coding: utf-8 -*-
import socket


class SubnetTest(object):
    def __init__(self, network):
        self.network, self.netmask = network.split('/')
        self._network_int = int(socket.inet_aton(self.network).encode('hex'), 16)
        self._mask = ((1L << int(self.netmask)) - 1) << (32 - int(self.netmask))
        self._net_prefix = self._network_int & self._mask

    def match(self, ip):
        '''
        判断传入的 IP 是不是本 Network 内的 IP
        '''
        ip_int = int(socket.inet_aton(ip).encode('hex'), 16)
        return (ip_int & self._mask) == self._net_prefix

st = SubnetTest('100.98.21.0/24')
print st.match('100.98.23.32')

إذا كنت لا ترغب في استيراد الوحدات الأخرى التي يمكنك الذهاب إليها:

def ip_matches_network(self, network, ip):
    """
    '{:08b}'.format(254): Converts 254 in a string of its binary representation

    ip_bits[:net_mask] == net_ip_bits[:net_mask]: compare the ip bit streams

    :param network: string like '192.168.33.0/24'
    :param ip: string like '192.168.33.1'
    :return: if ip matches network
    """
    net_ip, net_mask = network.split('/')
    net_mask = int(net_mask)
    ip_bits = ''.join('{:08b}'.format(int(x)) for x in ip.split('.'))
    net_ip_bits = ''.join('{:08b}'.format(int(x)) for x in net_ip.split('.'))
    # example: net_mask=24 -> compare strings at position 0 to 23
    return ip_bits[:net_mask] == net_ip_bits[:net_mask]

لقد جربت مجموعة فرعية واحدة من الحلول المقترحة في هذه الإجابات .. بدون نجاح ، قمت أخيرًا بتكييف الرمز المقترح وأصلحته وكتبت وظيفتي الثابتة.

لقد اختبرت ذلك وأعمل على الأقل على البنى الداخلية الصغيرة-egx86-إذا كان أي شخص يحب تجربة بنية إنديان كبيرة ، فالرجاء إعطائي التعليقات.

IP2Int الرمز يأتي من هذا المشنور, ، الطريقة الأخرى هي إصلاح بالكامل (لحالات الاختبار الخاصة بي) العمل للمقترحات السابقة في هذا السؤال.

الرمز:

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


def addressInNetwork(ip, net_n_bits):
    ipaddr = IP2Int(ip)
    net, bits = net_n_bits.split('/')
    netaddr = IP2Int(net)
    bits_num = int(bits)
    netmask = ((1L << bits_num) - 1) << (32 - bits_num)
    return ipaddr & netmask == netaddr & netmask

نأمل مفيدًا ،

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top