python解析CC++结构体二进制数据

python解析CC++结构体二进制数据,第1张


一、引言

socket为数据通信中必不可少的一部分,常用的有TCP数据传输协议和UDP数据传输协议。


(具体的socket详情这里不赘述)。


不论是TCP还是UDP,凡是涉及到数据传输,都需要进行数据内容解析。


而很多时候为了数据传输的有效性,一般都会制定协议,通过特定的协议进行数据通信。


统一语言的通信相对比较简单,而跨语言通信就比较复杂。


本文站在巨人的肩膀上,借鉴各位大神的经验和自己处理问题的心得,主要就是介绍python和C++跨语言进行数据通信,以及数据通信过程中需要制定的协议和相关的协议解析方式。



二、struct包概述

用python处理socket的二进制数据时就需要用到struct包,struct包主要包括calcsize, pack, unpack几个函数,可以用来处理C/C++的结构体数据结构


pack(fmt, v1, v2, …) 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)

unpack(fmt, string) 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple

calcsize(fmt) 计算给定的格式(fmt)占用多少字节的内存

struct中支持的数据格式:

FormatC TypePython字节
xpad byte(填充)no value
ccharstring of length 11
bsigned charint1
Bunsigned charint1
?_Boolbool1
hshortint2
Hunsigned shortint2
iintint4
Iunsigned intint4
llongint4
Lunsigned longlong4
qlong longlong8
Qunsigned long longlong8
ffloatfloat4
ddoublefloat88
schar[]string
pchar[]string
Pvoid *long

为了同c中的结构体交换数据,还要考虑有的c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:

CharacterByte orderSize & alignment
@nativenative
=nativestandard
<little-endianstandard
>big-endianstandard
!network(=bid-endian)standard

注:网络通信默认大端模式,不需要特殊指定。



三、包头解析

在团队开发的时候,存在多语言开发,如处理一下C++结构体:

struct Header
{
    int flag;
    char[4] tag;
    int aWidth;
    unsigned int version;
    unsigned int count;
} aHead;

本质上来讲,结构体作为一种数据结构,在python中同样适用。


只是python没有指针,想要解析结构体数据结构时使用struct.unpack即可。


ss = socket.recv(1024)
# i为int型,4s为4字节长度的字符串,2I为无符号int型;
flag, tag, width, version, count = struct.unpack('i4si2I', s)

多数帖子指出需要指定数据解析顺序,如网络数据'!4si2I',而根据本人实际测试,解析网络端数据无需指定解析顺序,即不需要<, >,即'4si2I'即可。



四、发送数据

Python给C++发送数据只需要将上述 *** 作反向 *** 作即可。


如发送flag, tag, width, version, count 给C++服务器,只需要将所有数据pack为二进制数据流发送即可。


flag = 2 # int
tag  = 'send' # str
width = 333  # int
version = 1.3.0 # unsigned int
count = 65535 # unsigned int

ss = struct.pack('i4si2I', flag, tag, width, version, count)
socket.send(ss)

一言以蔽之,可用struct对各种类型的数据打包转为二进制数据流。


如:

a = 11
byte_a = struct.pack('i', a) # int型pack
get_a = struct.unpack('i', byte_a) # 反 *** 作,转为int型

因此,只需要按照(二)struct概述所示的struct所支持的数据格式,按照指定的语言规则(传输协议)进行数据格式转换并且发送/接收即可。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/634448.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-16
下一篇 2022-04-16

发表评论

登录后才能评论

评论列表(0条)

保存