我正在尝试使用MessagePack序列化Delphi中的Record,然后使用ZeroMQ TCP协议将其发送到Python服务器。
b'\xa8DataType\x01\xa4data\xbf{"major":1,"minor":0,"build":2}\x00'
我在服务器端反序列化时遇到问题。任何想法为什么会这样?是某种编码问题吗?谢谢!
更新#1:
我使用www.msgpack.org推荐的messagepack库“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是一个设置为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]
为什么?
答案 0 :(得分:1)
打包数据似乎无效。
>>> 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中所见,它是一个两个条目的修复映射。
您的打包数据缺少该信息,并直接启动到fixstr。所以,是的,基于Delphi的打包程序和基于Python的解包程序之间可能存在不匹配。但是,当我使用你的Delphi代码,使用repo中最新的qmsgpack时,它产生以下字节:
82A8446174615479706501A464617461 BF7B226D616A6F72223A312C226D696E 6F72223A312C226275696C64223A317D
让它将其转换为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编码数据。所以这是做什么的:
data
字段的类型从string
更改为TBytes
。那是因为我们要在那里放一个字节数组。data
填充Encode
字段,如下所示:packet.data := lvMsg.Encode
。data
时,你会发现它是一个整数数组。将其转换为字节,然后解压缩:umsgpack.unpackb(bytes(data))
。