0

我正在寻求您的帮助,因为我已经被同样的问题困扰了 3 天。如果我有 :

Value1 = 0, Value2 = 3.10 and IPv6 = '2001::1'

我想用这个命令打包所有 3 个值:package = struct.pack(*format*, value1, value2, IPv6)

我的问题是:我不知道我可以使用 C 类型中的什么格式字符来打包 IPv6 并保留其 16 个字节。我知道我可以用format = 'i f ?'i 表示整数 / f 表示浮点数,但我需要找到用什么来替换“?” 是 IPv6 地址的 C 类型格式字符,用于打包这三个值。

拜托,有人可以帮助我吗?

4

1 回答 1

0

使用它并不是那么简单struct,因为在将其添加到结构之前,您必须知道 IPv6 地址的正确字节值。'2001::1' 是一种文本表示,它远不能为您提供这些值:您必须将字符串拆分:为打包在结构中。当然,在 IPv6 字符串表示中存在一些极端情况和特殊语法,您必须考虑到这一点。

幸运的是,Python 已经在 . ipaddress标准库的模块。

只需 import ipaddress,为包的第一部分格式化结构,并将其与 IPv6Address Python 中的“packed”属性连接起来,Python 会自动为您分类:

import struct
import ipaddress


Value1 = 0
Value2 = 3.10 
IPv6 = '2001::1'

payload = struct.pack("if", (Value1, Value2)) + ipaddress.ip_address(IPv6).packed

但是,我想知道以这种方式简单地打包一个 int 和一个 float 以及一个 IP 地址是否会有效——无论读取什么代码,它都将与您正在写入的代码超级耦合。如果您只是将它存储到一个文件中以供您控制下的 Python 程序读回,请pickle改用它。如果您打算通过网络将这些值发送到非 Python 程序,那么像 JSON 这样的无模式文本传输方式可能会简单得多。

如果您真的想以紧凑的方式存储这些,并且只有这些,以节省空间,并且它们有成千上万个,它们将被同一个程序读回:尝试 numpy 数组。它们将处理每种对象类型的紧凑二进制表示,并且可以读取和写入二进制文件,而 numpy 将为您处理记录偏移量。

我能看到的唯一用例是,如果您有一个不受您控制的程序在低级协议中,该协议将完全期望这种记录格式。由于您正在推测如何创建有效负载,并试图将“3.10”作为浮点值传达,因此情况似乎并非如此。谈到这一点,“3.10”或其他数字可能不会像这样的结构良好形成的 2 位十进制数字值往返,因为浮点数在内部是如何表示的。我建议你在那里回顾你的目标和需求,不要把事情复杂化。

要解压,更简单的方法是使用 struct 仅恢复数值,并将剩余的 16 个字节传回ip_address工厂函数 - 它会自动创建一个 IPv6 对象,该字符串表示为人类友好的“2001::1” .

我在交互式提示中键入“往返”:

In [30]: import struct, ipaddress

In [31]: x = ipaddress.ip_address('2001::1')

In [32]: v1 = 2;v2 = 3.10

In [33]: payload = struct.pack(">if",v1, v2) + x.packed

In [34]: print(payload)
b'\x00\x00\x00\x02@Fff \x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'

In [35]: v3, v4, nx = struct.unpack(">if", aa[:-16]) + (ipaddress.ip_address(aa[-16:]),)

In [36]: print(v3, v4, nx)
2 3.0999999046325684 2001::1

需要注意的两件事:在>结构格式化字符串上添加的前缀,以确保编码其内容时的字节顺序,以及如上所述的“3.10”值不会作为“漂亮的小数点后两位”值往返。round(number, 2)如果需要,在服务器端表示数字时使用。

于 2021-12-07T14:27:37.333 回答