我有一个从C++程序发送的UDP包,我必须用Python阅读它。我成功地接收了UDP包,但不幸的是它被编码了。C++数据具有以下形式
struct packet{
double arg1
double arg2
double arg3
double arg4
int16_t arg5
};我收到的数据总共有42个字节长(与发送的长度相同)。也许在发送数据之前,数据也略有变化,但我仍在试图弄清楚这一点。因此,我的问题是:假设发送的数据的结构与上面描述的完全相同。我怎么能从缓冲区里读出来呢?(顺便说一句。我正在使用Python 2.7.9)
Thx已经
编辑:我发现了一些关于这个结构的东西
void Send(const CrazyFliePacket& packet)
{
FMA::ByteBuffer p =
FMA::Encode((PACKET_TYPE)FMA_PACKET_TYPES::CRAZYFLIE) +
FMA::Encode((PACKET_VERSION)0) +
FMA::Encode(_seq++) +
packet.Encode();
_server->SendPacket(p.data(),p.size());
printf("Packet sent with %i bytes size\n",p.size());
}类型如下:
typedef unsigned short PACKET_TYPE;
typedef unsigned short PACKET_VERSION;
uint16_t _seq;发送和接收的数据现在有40个字节长。
Edit2:正确的解决方案是
print struct.unpack('<HHhddddh', data)发布于 2015-03-13 10:12:45
我认为结构是你要找的。无论如何,您必须找到序列化的数据格式。发送的不是C/C++结构,而是一种描述良好的序列化格式,可能是binaray。重要的话题有:小/大,双倍大小,整数和衬垫大小。
from struct import *
arg1, arg2, arg3, arg4, arg5 = unpack('!ddddi', buffer)标准大小需要36个字节。
>>> from struct import *
>>> a='\x00\x00\x00\x01'*9
>>> unpack('>ddddi', a)
(2.1219957915e-314, 2.1219957915e-314, 2.1219957915e-314, 2.1219957915e-314, 1)
>>> unpack('<ddddi', a)
(7.291122046717944e-304, 7.291122046717944e-304, 7.291122046717944e-304, 7.291122046717944e-304, 16777216)
>>> unpack('!ddddi', a)
(2.1219957915e-314, 2.1219957915e-314, 2.1219957915e-314, 2.1219957915e-314, 1)
>>>编辑:将变量解压缩为元组和类
直接解压缩到变量
from struct import unpack
b = "\x00\x00\x00\x05\x00\x00\x00\x2a"
x, y = unpack('!ii', b)
print x
print y将包解压缩为命名元组
from struct import unpack
from collections import namedtuple
b = "\x00\x00\x00\x05\x00\x00\x00\x2a"
Point = namedtuple('Point', 'x, y')
p = Point._make(unpack("!ii", b))
print p.x
print p.y记住:元组属性是只读的。
解压缩并使类无效
from struct import unpack
b = "\x00\x00\x00\x05\x00\x00\x00\x2a"
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(*unpack('!ii', b))
print p.x
print p.y发布于 2015-03-13 14:14:30
我也使用了struct解包(每次都要搜索字符代码),直到我学会了使用ctype来做同样的事情。我不知道哪一个执行得更快,但我知道只看C定义就可以翻译哪一个没有问题。
from ctypes import LittleEndianStructure, BigEndianStructure, c_int16, c_double, sizeof
#there are bit explicit types if you want to fix the size, like c_int8/16/32/64
class Packet(LittleEndianStructure): # replace by BigEndian as needed
_fields_ = [
("arg1", c_double),
("arg1", c_double),
("arg3", c_double),
("arg4", c_double),
("arg5", c_int16)
]
_pack_=1 # comment this or not depending on padding
mypacket = Packet.from_buffer_copy(payload)它对我来说容易得多,而且它的优点是为我提供了一个收集所有数据并可以按名称访问的对象。
print(mypacket.arg1)https://stackoverflow.com/questions/29028876
复制相似问题