在Delphi中使用MessagePack序列化用户定义的类型时可能出现编码问题?

2024-09-30 10:30:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在Delphi中序列化一条记录,方法是使用MessagePack,然后使用zeromqtcp协议将其发送到Python服务器。在

b'\xa8DataType\x01\xa4data\xbf{"major":1,"minor":0,"build":2}\x00'

我在服务器端无法反序列化它。你知道为什么会这样吗?是某种编码问题吗?谢谢!在

更新1:

我使用在www.msgpack.org上推荐的messagepack库“QMsgPack”。下面是一些Delphi代码。我的用户定义记录和枚举:

^{pr2}$

以及序列化对象的代码:

begin
    dmVersion.major := 1;
    dmVersion.minor := 1;
    dmVersion.build := 1;

    lvMsg := TQMsgPack.Create;
    lvMsg.FromRecord(dmVersion);

    lvMsgString := lvMsg.ToString();

    packet.DataType := dtVersion;
    packet.data := lvMsgString;
    lvMsg.Clear;
    lvMsg.FromRecord(packet);
    lvbytes:=lvMsg.Encode;
    ZeroMQ.zSendByteArray(skt, lvbytes);

然后,我尝试在python服务器中对接收到的字节数组进行反序列化,如下所示:

b'\xa8DataType\x01\xa4data\xbf{"major":1,"minor":0,"build":2}\x00'

通过使用umsgpack.unpack(),然后在结果中打印出如下结果:

packet_packed = command.recv()

# Unpack the packet
umsgpack.compatibility = True
packet = umsgpack.unpackb( packet_packed )
print (packet) 
for item in packet:
    print (item)

我在屏幕上看到的是:

b'DataType'
68
97
116
97
84
121
112
101

我希望这有帮助!谢谢!在

更新2

下面是一些python端的服务器代码。VDS_PACKET_版本是设置为1的常量int。在

    # Make sure its a version packet
    if VDS_PACKET_VERSION == packet[0]:

        # Unpack the data portion of the packet
        version = umsgpack.unpackb( packet[1] )

        roster = []
        if ( VDS_VERSION_MAJOR == version[0] ) and ( VDS_VERSION_MINOR == version[1] ) and ( VDS_VERSION_BUILD == version[2] ):
            dostuff()

使用当前序列化对象

b'\x82\xa8DataType\x01\xa4data\xbf{"major":1,"minor":1,"build":1}'

我明白了

KeyError: 0 on packet[0]

为什么?在


Tags: build服务器序列化packetversionminorx01major
1条回答
网友
1楼 · 发布于 2024-09-30 10:30:44

压缩数据似乎无效。在

>>> packet = { "DataType": 1, "data": "{\"major\":1,\"minor\":0,\"build\":2}"}
>>> umsgpack.packb(packet)
b'\x82\xa4data\xbf{"major":1,"minor":0,"build":2}\xa8DataType\x01'

第一个字节是\x82,正如在specification中看到的那样,它是一个两个条目的fixmap。在

打包的数据缺少这些信息,直接进入fixstr。所以,是的,基于Delphi的打包机和基于Python的解包器可能不匹配。但是,当我使用repo中最新的qmsgpack获取Delphi代码时,它会生成以下字节:

^{pr2}$

让我们把它转换成Python字节对象。看起来像这样:

b'\x82\xa8DataType\x01\xa4data\xbf{"major":1,"minor":1,"build":1}'

现在,这和你报告的完全不同。并且umsgpack可以很好地解压它。注意,第一个字节是\x82,一个两个条目的fixmap,正如预期的那样。是的,条目的顺序不同,但没关系。顺序对于地图来说并不重要。在

所以,我已经能够在Delphi中使用qmsgpack进行编码,并在Python中使用umsgpack进行解码。这说明这个问题确实在传播中。在我看来好像有一个错误。不是发送字节0到N-1,而是发送了字节1到N。注意接收到的数据中的伪尾随零。在


在注释中,data字段被编码为JSON并作为字符串传递。但您宁愿使用MessagePack对数据进行编码。所以我们要做的是:

  1. 在Delphi代码中,将data字段的类型从string更改为{}。这是因为我们要在里面放一个字节数组。在
  2. 使用Encode填充data字段,如下所示:packet.data := lvMsg.Encode。在
  3. 在Python方面,当您解压缩data时,您会发现它是一个整数数组。将其转换为字节,然后解压缩:umsgpack.unpackb(bytes(data))。在

相关问题 更多 >

    热门问题