2013-07-15 2 views
0

Я пытаюсь преобразовать группу диапазонов IP, которые могут начинаться и заканчиваться на любом заданном адресе, но не обязательно на .0, .127 или .255 и т. Д. У меня есть код, который в основном работает; однако он может быть медленным для больших диапазонов.IP-адресные сети в Python 3.3

Например, find_range("1.40.0.0","1.44.255.255") займет более минуты, чтобы вернуть правильный результат 1.40.0.0/14 и 1.44.0.0/16.

Кроме того, у меня возникают проблемы, когда начальный диапазон не заканчивается на .0. Как я могу исправить эти 2 проблемы: медленность на больших диапазонах IP и когда начальный диапазон не заканчивается на .0?

Для проблемы с медлительностью я попытался пропустить более 1 адреса за раз, но тогда это пропустит меньшие диапазоны.

import ipaddress, socket, struct 

def ip2int(addr):                
    return struct.unpack("!I", socket.inet_aton(addr))[0]      

def int2ip(addr):                
    return socket.inet_ntoa(struct.pack("!I", addr))   

def ipminus(ip, amount=1): 
    tmp = ip2int(ip) 
    return int2ip(tmp - amount) 

def ipplus(ip): 
    tmp = ip2int(ip) 
    return int2ip(tmp + 1) 

def cidr_notation(a,b): 
    for mask in range(32, 6, -1): 
     test = "%s/%s" % (a,mask) 
     try: 
      n = ipaddress.IPv4Network(test,False) 
      if b == "%s" % (n.broadcast_address): 
       return test 
     except: 
      pass 
    return None 

def split_range(a,b): 
    a1 = ip2int(a) 
    b1 = ip2int(b) 

    needed = 1 
    while needed: 
     result = cidr_notation(a,b) 
     if result: 
      print("* %16s\t%16s\t%16s" % (result, a, b)) 
      if ip2int(b) > b1: 
       needed = 0 
      else: 
       a = ipplus(b) 
       b = int2ip(b1) 
     else: 
      b = ipminus(b) 

    return result 

def find_range(x,y): 
    result = cidr_notation(x,y) 
    if result: 
     print("# %16s\t%16s\t%16s" % (result, x, y)) 
    else: 
     split_range(x,y) 

# main... 
print("%16s\t%16s\t%16s" % ("mask","start","end")) 
print("%16s\t%16s\t%16s" % ("----","-----","---")) 

find_range("128.191.0.0","128.191.255.255") #fast 
find_range("10.55.96.106","10.55.96.106") #fast 
find_range("5.135.14.0","5.135.61.11") #slow 
find_range("4.31.64.72","4.59.175.255") #does not work, how to fix? 
find_range("1.40.0.0","1.44.255.255") #very slow 
# 5000 more find_range() calls... 
+1

Вы пробовали посмотреть этот существующий код с ipaddress.py? https://code.google.com/p/ipaddress-py/source/browse/ipaddress.py#248 –

+0

@bsdlp: Это похоже на то, что мне нужно. Благодаря! – jftuga

ответ

1

Основано на комментарии пользователя bsdlp, этот код стал намного проще и быстрее!

def find_range(x,y,c_code="",c_name=""): 
    print() 
    print("%29s\t%23s" % (x,y)) 
    print("%16s\t%16s\t%16s\t%4s\t%s" % ("mask","start","end","code","name")) 
    print("%16s\t%16s\t%16s\t%4s\t%s" % ("----","-----","---","----","----")) 

    result = ipaddress.summarize_address_range(ipaddress.IPv4Address(x), ipaddress.IPv4Address(y)) 
    for entry in result: 
     net = str(entry.network_address) 
     bcast = str(entry.broadcast_address) 
     print("%16s\t%16s\t%16s\t%4s\t%s" % (entry, net, bcast,c_code,c_name))