可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
i have a little problem with my script, where i need to convert ip in form 'xxx.xxx.xxx.xxx' to integer representation and go back from this form.
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`
Anybody knows how to fix that?
回答1:
#!/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
回答2:
Python 3 has ipaddress module which features very simple conversion:
int(ipaddress.IPv4Address("192.168.0.1"))
str(ipaddress.IPv4Address(3232235521))
回答3:
In pure python without use additional module
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))
Result:
192.168.0.1 -> 3232235521
3232235521 -> 192.168.0.1
回答4:
You lose the left-zero-padding which breaks decoding of your string.
Here's a working function:
def inttoip(ip):
return socket.inet_ntoa(hex(ip)[2:].zfill(8).decode('hex'))
回答5:
Below are the fastest and most straightforward (to the best of my knowledge)
convertors for IPv4 and 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))
Python code not using inet_ntop()
and struct
module is like order of magnitude slower than this regardless of what it is doing.
回答6:
One line
reduce(lambda out, x: (out << 8) + int(x), '127.0.0.1'.split('.'), 0)
回答7:
Let me give a more understandable way:
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
The above:
lst = [int(item) for item in s_ip.split('.')]
equivalent to :
lst = map(int, s_ip.split('.'))
also:
int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24
equivalent to :
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])
or:
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)
回答8:
My approach is to straightforwardly look at the the number the way it is stored, rather than displayed, and to manipulate it from the display format to the stored format and vice versa.
So, from an IP address to an int:
def convertIpToInt(ip):
return sum([int(ipField) << 8*index for index, ipField in enumerate(reversed(ip.split('.')))])
This evaluates each field, and shifts it to its correct offset, and then sums them all up, neatly converting the IP address' display into its numerical value.
In the opposite direction, from an int to an IP address:
def convertIntToIp(ipInt):
return '.'.join([str(int(ipHexField, 16)) for ipHexField in (map(''.join, zip(*[iter(str(hex(ipInt))[2:].zfill(8))]*2)))])
The numerical representation is first converted into its hexadecimal string representation, which can be manipulated as a sequence, making it easier to break up. Then, pairs are extracted by mapping ''.join onto tuples of pairs provided by zipping a list of two references to an iterator of the IP string (see How does zip(*[iter(s)]*n) work?), and those pairs are in turn converted from hex string representations to int string representations, and joined by '.'.
回答9:
I used following:
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'