1

我正在尝试使用 MessagePack 序列化 Delphi 中的记录,然后使用 ZeroMQ TCP 协议将其发送到 Python 服务器。

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

我在服务器端反序列化它时遇到问题。任何想法为什么会发生这种情况?是某种编码问题吗?谢谢!

更新#1:

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

Version = Record
    major : Integer;
    minor : Integer;
    build : Integer;
end;

TDataType = (dtUnset, dtVersion, dtEntityDescription, dtEntityDescriptionVector, dtEntityState, dtEntityStateVector, dtCommandContinue, dtCommandComplete);

TPacket = Record
    DataType : TDataType;
    data : string;
end;

以及序列化对象的代码:

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_VERSION 是一个常量 int,设置为 1。

    # 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]

这是为什么?

4

1 回答 1

1

打包数据似乎无效。

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

从规范\x82中可以看出,第一个字节是一个两个条目的固定映射。

您的打包数据缺少该信息,并直接启动到 fixstr。所以,是的,基于 Delphi 的打包器和基于 Python 的解包器之间可能存在不匹配。但是,当我使用来自 repo 的最新 qmsgpack 获取您的 Delphi 代码时,它会生成以下字节:

82A8446174615479706501A464617461
BF7B226D616A6F72223A312C226D696E
6F72223A312C226275696C64223A317D

让我们将其转换为 Python 字节对象。它看起来像这样:

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

现在,这与您报告的情况完全不同。并且umsgpack可以很好地打开它。请注意,\x82正如预期的那样,第一个字节是两个条目的修复图。是的,条目的顺序不同,但这很好。顺序对于地图并不重要。

因此,我已经能够在 Delphi 中使用 qmsgpack 进行编码,并在 Python 中使用 umsgpack 进行解码。这表明这个问题确实存在于传输中。在我看来,好像出现了一个错误。不是发送字节 0 到 N-1,而是发送字节 1 到 N。请注意接收到的数据中的虚假尾随零。


在评论中,您认为该data字段被编码为 JSON 并作为字符串传递。但您宁愿使用 MessagePack 对数据进行编码。所以这里是做什么:

  1. 在 Delphi 代码中,将data字段的类型从更改stringTBytes。那是因为我们要在其中放置一个字节数组。
  2. 使用填充data字段Encode,如下所示packet.data := lvMsg.Encode
  3. 在 Python 端,当你解包时,data你会发现它是一个整数数组。将其转换为字节,然后解包:umsgpack.unpackb(bytes(data))
于 2014-09-15T11:14:21.453 回答