Python将IP字符串打包为字节

3

我希望自己实现一个struct.pack的函数,可以将IP地址字符串(例如“192.168.0.1”)打包成32位压缩值,而不使用内置方法socket.inet_aton

我已经完成了以下部分:

ip = "192.168.0.1"
hex_list = map(hex, map(int, ip.split('.')))
# hex list now is : ['0xc0', '0xa8', '0x0', '0x01']

我的问题是: 如何将 ['0xc0', '0xa8', '0x0', '0x01'] 转换为 '\xc0\xa8\x00\x01',(这是我从 socket.inet_aton(ip) 获取到的内容)?

(另外 - 为什么字符串中间有一个 NUL (\x00)?我认为我缺乏对 \x 格式的理解)

3个回答

2

一种替代方案:

你可以使用ipaddressto_bytes(Python 3.2)吗?

>>> import ipaddress
>>> address = ipaddress.IPv4Address('192.168.0.1')
>>> address_as_int = int(address)
>>> address_as_int.to_bytes(4, byteorder='big')
b'\xc0\xa8\x00\x01'

请注意,您可能只需要整数。
显然可以更短,但我想清楚地展示所有步骤 :)

2
您可以使用字符串推导式按照您的喜好进行格式化:
ip = "192.168.0.1"
hex_list = map(int, ip.split('.'))
hex_string = ''.join(['\\x%02x' % x for x in hex_list])

或者作为一行代码:

hex_string = ''.join(['\\x%02x' % int(x) for x in ip.split('.')])

1
我尝试了一下,但是得到的是 '\xc0\xa8\x00\x01',这与 '\xc0\xa8\x00\x01' 不相等。它们是一样的吗? - Ofer Arial
\\ 只是 Python 显示单个 \ 的方式。将 '\\x%02x' 更改为 r'\x%02x',注意你会得到相同的结果。 - Stephen Rauch
我知道,但是当我发送这个地址时,它会保持不变吗?它会与 socket.inet_aton 接收到的值相同吗? - Ofer Arial
转义字符串有点像黑魔法。答案是:这取决于情况。在每个步骤中,都有可能需要对字符串进行解释,因此需要某种形式的转义。我只是回答了你如何获取指定字符串的问题。 - Stephen Rauch
谢谢你的回答! - Ofer Arial

1

基于 @Stephen 的答案,但返回一个包含实际字节的字符串,而不是带有转义斜杠的字符串:

def pack_ip(ip):
    num_list = map(int, ip.split('.'))
    return bytearray(num_list)

src_ip = pack_ip('127.0.0.255')
print(repr(src_ip))

适用于Python 2和3。返回b''而不是字符串,符合Python3的最佳实践。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接