以64位编码两个ipv4地址

时间:2016-07-21 15:32:24

标签: python

如果我有一对IP地址,如:

IP1="168.2.65.33"
IP2="192.4.2.55"

我想将每对编码为64位值,以便前32位是第一个IP地址,第二个是第二个IP地址。然后,我希望能够将64位值保存到文件中,以便我可以将其读回并恢复两个IP地址。

目标是节省空间。

是否可以在python中执行此操作?

3 个答案:

答案 0 :(得分:5)

不要担心以64位编码。 IPv4地址是32位(4字节)。如果将其中两个写入文件,则大小为8个字节。

使用socket.inet_aton将人类可读的IP地址 string 转换为压缩二进制原始4字节字符串:

import socket
ip_addrs = ["168.2.65.33", "192.4.2.55"]

with open('data.out', 'wb') as f:
    for ip in ip_addrs:
        raw = socket.inet_aton(ip)
        f.write(raw)

结果:

$ hexdump -Cv data.out 
00000000  a8 02 41 21 c0 04 02 37                           |..A!...7|
00000008

互补转换函数socket.inet_ntoa将打包的4字节字符串转换回人类可读的IP地址。

以下是编写和阅读它们的示例:

import socket

ip_pairs = [
    ('1.1.1.1', '1.1.1.2'),
    ('2.2.2.2', '2.2.2.3'),
    ('3.3.3.3', '3.3.3.4'),
]

# Write them out
with open('data.out', 'wb') as f:
    for ip1, ip2 in ip_pairs:
        raw = socket.inet_aton(ip1) + socket.inet_aton(ip2)
        f.write(raw)

def read_with_eof(f, n):
    res = f.read(n)
    if len(res) != n:
        raise EOFError
    return res

# Read them back in
result = []
with open('data.out', 'rb') as f:
    while True:
        try:
            ip1 = socket.inet_ntoa(read_with_eof(f, 4))
            ip2 = socket.inet_ntoa(read_with_eof(f, 4))
            result.append((ip1, ip2))
        except EOFError:
            break

print 'Input:', ip_pairs
print 'Result:', result

输出:

$ python pairs.py 
Input: [('1.1.1.1', '1.1.1.2'), ('2.2.2.2', '2.2.2.3'), ('3.3.3.3', '3.3.3.4')]
Result: [('1.1.1.1', '1.1.1.2'), ('2.2.2.2', '2.2.2.3'), ('3.3.3.3', '3.3.3.4')]

答案 1 :(得分:1)

是的,有可能,就像这样:

import struct
import os
IP1="168.2.65.233"
IP2="192.4.2.55"
s = struct.pack('>8B', *map(int, IP1.split('.') + IP2.split('.')))
with open('f', 'wb') as f:
  f.write(s)
print(os.stat('f').st_size)  #: 8.

这适用于Python 2和3。

根据Jonathon Reinhart的回答,您还可以使用socket.inet_aton代替struct.pack

答案 2 :(得分:1)

在Python3中,有一个用于处理IP的ipaddress模块。将它们分成32位并将它们加在一起:

from ipaddress import ip_address

original1 = ip_address('192.168.0.1')
original2 = ip_address('8.8.8.8')

out = original1.packed + original2.packed

将它们装回:

loaded1 = ip_address(out[0:4])
loaded2 = ip_address(out[4:])

在线试用:https://repl.it/Ce3k/1