j'ai un petit problème avec mon script, où j'ai besoin de convertir ip sous la forme 'xxx.xxx.xxx.xxx' en représentation entière et revenir de cette forme.
def iptoint(ip):
return int(socket.inet_aton(ip).encode('hex'),16)
def inttoip(ip):
return socket.inet_ntoa(hex(ip)[2:].decode('hex'))
In [65]: inttoip(iptoint('192.168.1.1'))
Out[65]: '192.168.1.1'
In [66]: inttoip(iptoint('4.1.75.131'))
---------------------------------------------------------------------------
error Traceback (most recent call last)
/home/thc/<ipython console> in <module>()
/home/thc/<ipython console> in inttoip(ip)
error: packed IP wrong length for inet_ntoa`
Quelqu'un sait comment résoudre ce problème?
#!/usr/bin/env python
import socket
import struct
def ip2int(addr):
return struct.unpack("!I", socket.inet_aton(addr))[0]
def int2ip(addr):
return socket.inet_ntoa(struct.pack("!I", addr))
print(int2ip(0xc0a80164)) # 192.168.1.100
print(ip2int('10.0.0.1')) # 167772161
Python 3 a ipaddress module qui présente une conversion très simple:
int(ipaddress.IPv4Address("192.168.0.1"))
str(ipaddress.IPv4Address(3232235521))
En python pur sans utiliser de module supplémentaire
def IP2Int(ip):
o = map(int, ip.split('.'))
res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
return res
def Int2IP(ipnum):
o1 = int(ipnum / 16777216) % 256
o2 = int(ipnum / 65536) % 256
o3 = int(ipnum / 256) % 256
o4 = int(ipnum) % 256
return '%(o1)s.%(o2)s.%(o3)s.%(o4)s' % locals()
# Example
print('192.168.0.1 -> %s' % IP2Int('192.168.0.1'))
print('3232235521 -> %s' % Int2IP(3232235521))
Résultat:
192.168.0.1 -> 3232235521
3232235521 -> 192.168.0.1
Vous perdez le remplissage à zéro zéro qui interrompt le décodage de votre chaîne.
Voici une fonction de travail:
def inttoip(ip):
return socket.inet_ntoa(hex(ip)[2:].zfill(8).decode('hex'))
Vous trouverez ci-dessous les convertisseurs les plus rapides et les plus simples (à ma connaissance) Pour IPv4 et IPv6:
try:
_str = socket.inet_pton(socket.AF_INET, val)
except socket.error:
raise ValueError
return struct.unpack('!I', _str)[0]
-------------------------------------------------
return socket.inet_ntop(socket.AF_INET, struct.pack('!I', n))
-------------------------------------------------
try:
_str = socket.inet_pton(socket.AF_INET6, val)
except socket.error:
raise ValueError
a, b = struct.unpack('!2Q', _str)
return (a << 64) | b
-------------------------------------------------
a = n >> 64
b = n & ((1 << 64) - 1)
return socket.inet_ntop(socket.AF_INET6, struct.pack('!2Q', a, b))
Le code Python n'utilisant pas les modules inet_ntop()
et struct
est comme un ordre de grandeur plus lent que cela indépendamment de ce qu'il fait.
Une ligne
reduce(lambda out, x: (out << 8) + int(x), '127.0.0.1'.split('.'), 0)
Mon approche consiste à regarder directement le nombre de la manière dont il est stocké, plutôt qu’à l’afficher, et à le manipuler du format d’affichage au format enregistré et vice-versa.
Donc, d'une adresse IP à un int:
def convertIpToInt(ip):
return sum([int(ipField) << 8*index for index, ipField in enumerate(reversed(ip.split('.')))])
Ceci évalue chaque champ et le décale vers son offset correct, puis les additionne, convertissant avec précision l'affichage de l'adresse IP en valeur numérique.
Dans le sens opposé, d'un int à une adresse IP:
def convertIntToIp(ipInt):
return '.'.join([str(int(ipHexField, 16)) for ipHexField in (map(''.join, Zip(*[iter(str(hex(ipInt))[2:].zfill(8))]*2)))])
La représentation numérique est d'abord convertie en sa représentation sous forme de chaîne hexadécimale, qui peut être manipulée sous forme de séquence, ce qui facilite sa fragmentation. Ensuite, les paires sont extraites en mappant '' .join sur des nuplets de paires fournis en zippant une liste de deux références à un itérateur de la chaîne IP (voir Comment fonctionne Zip (* [iteur (s)] * n)? ), et ces paires sont à leur tour converties de représentations de chaîne hexagonale en représentations de chaîne int, et jointes par '.'.
ip2int = lambda ip: reduce(lambda a,b: long(a)*256 + long(b), ip.split('.'))
ip2int('192.168.1.1')
#output
3232235777L
# from int to ip
int2ip = lambda num: '.'.join( [ str((num >> 8*i) % 256) for i in [3,2,1,0] ])
int2ip(3232235777L)
#output
'192.168.1.1'
Laissez-moi vous donner une façon plus compréhensible:
ip to int
def str_ip2_int(s_ip='192.168.1.100'):
lst = [int(item) for item in s_ip.split('.')]
print lst
# [192, 168, 1, 100]
int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24
return int_ip # 3232235876
Ce qui précède:
lst = [int(item) for item in s_ip.split('.')]
équivalent à :
lst = map(int, s_ip.split('.'))
également:
int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24
équivalent à :
int_ip = lst[3] + (lst[2] << 8) + (lst[1] << 16) + (lst[0] << 24)
int_ip = lst[3] + lst[2] * pow(2, 8) + lst[1] * pow(2, 16) + lst[0] * pow(2, 24)
int to ip:
def int_ip2str(int_ip=3232235876):
a0 = str(int_ip & 0xff)
a1 = str((int_ip & 0xff00) >> 8)
a2 = str((int_ip & 0xff0000) >> 16)
a3 = str((int_ip & 0xff000000) >> 24)
return ".".join([a3, a2, a1, a0])
ou:
def int_ip2str(int_ip=3232235876):
lst = []
for i in xrange(4):
shift_n = 8 * i
lst.insert(0, str((int_ip >> shift_n) & 0xff))
return ".".join(lst)