首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python缓冲区解码

Python缓冲区解码
EN

Stack Overflow用户
提问于 2015-03-13 09:34:33
回答 2查看 2.4K关注 0票数 1

我有一个从C++程序发送的UDP包,我必须用Python阅读它。我成功地接收了UDP包,但不幸的是它被编码了。C++数据具有以下形式

代码语言:javascript
复制
struct packet{
    double arg1
    double arg2
    double arg3
    double arg4
    int16_t arg5
};

我收到的数据总共有42个字节长(与发送的长度相同)。也许在发送数据之前,数据也略有变化,但我仍在试图弄清楚这一点。因此,我的问题是:假设发送的数据的结构与上面描述的完全相同。我怎么能从缓冲区里读出来呢?(顺便说一句。我正在使用Python 2.7.9)

Thx已经

编辑:我发现了一些关于这个结构的东西

代码语言:javascript
复制
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());
    }

类型如下:

代码语言:javascript
复制
typedef unsigned short PACKET_TYPE;
typedef unsigned short PACKET_VERSION;
uint16_t _seq;

发送和接收的数据现在有40个字节长。

Edit2:正确的解决方案是

代码语言:javascript
复制
print struct.unpack('<HHhddddh', data)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-13 10:12:45

我认为结构是你要找的。无论如何,您必须找到序列化的数据格式。发送的不是C/C++结构,而是一种描述良好的序列化格式,可能是binaray。重要的话题有:小/大,双倍大小,整数和衬垫大小。

代码语言:javascript
复制
from struct import *
arg1, arg2, arg3, arg4, arg5 = unpack('!ddddi', buffer)

标准大小需要36个字节。

代码语言:javascript
复制
>>> 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)
>>>

编辑:将变量解压缩为元组和类

直接解压缩到变量

代码语言:javascript
复制
from struct import unpack 
b = "\x00\x00\x00\x05\x00\x00\x00\x2a"

x, y = unpack('!ii', b)
print x
print y

将包解压缩为命名元组

代码语言:javascript
复制
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

记住:元组属性是只读的。

解压缩并使类无效

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2015-03-13 14:14:30

我也使用了struct解包(每次都要搜索字符代码),直到我学会了使用ctype来做同样的事情。我不知道哪一个执行得更快,但我知道只看C定义就可以翻译哪一个没有问题。

代码语言:javascript
复制
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)

它对我来说容易得多,而且它的优点是为我提供了一个收集所有数据并可以按名称访问的对象。

代码语言:javascript
复制
print(mypacket.arg1)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29028876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档