了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对某一结构对象进行处理。而在网络通信当中,大多传递的数据是以二进制流(binary data)存在的。当传递字符串时,不必担心太多的问题,而当传递诸如int、char之类的基本数据的时候,就需要有一种机制将某些特定的结构体类型打包成二进制流的字符串然后再网络传输,而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。python中的struct模块就提供了这样的机制,该模块的主要作用就是对python基本类型值与用python字符串格式表示的C struct类型间的转化(This module performs conversions between Python values and C structs represented as Python strings.)。stuct模块提供了很简单的几个函数,下面写几个例子。
该模块作用是完成Python数值和C语言结构体的Python字符串形式间的转换。这可以用于处理存储在文件中或从网络连接中存储的二进制数据,以及其他数据源。
用途: 在Python基本数据类型和二进制数据之间进行转换
struct模块提供了用于在字节字符串和Python原生数据类型之间转换函数,比如数字和字符串。
模块函数和Struct类
它除了提供一个Struct类之外,还有许多模块级的函数用于处理结构化的值。这里有个格式符(Format specifiers)的概念,是指从字符串格式转换为已编译的表示形式,类似于正则表达式的处理方式。通常实例化Struct类,调用类方法来完成转换,比直接调用模块函数有效的多。下面的例子都是使用Struct类。
Packing(打包)和Unpacking(解包)
Struct支持将数据packing(打包)成字符串,并能从字符串中逆向unpacking(解压)出数据。
在本例中,格式指定器(specifier)需要一个整型或长整型,一个两个字节的string,和一个浮点数。格式符中的空格用于分隔各个指示器(indicators),在编译格式时会被忽略。
-
struct模块中最重要的二个函数是pack(), unpack():
(1)打包:struct.pack(fmt, v1, v2, …)
(2)解包:struct.unpack(fmt, buffer)
-
struct中支持的格式字符(fmt)如下表。
-
字节顺序,大小和对齐。默认情况下,C类型以机器的本机格式和字节顺序表示,并且如果必要,通过跳过填充字节(根据C编译器使用的规则)正确对齐。
或者,根据下表,格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐。使用方法是放在fmt的第一个位置,就像'@5s5sif'。
-
-
网络字节顺序。您也可以使用网络字节顺序将其发送到网络。
-
举例理解1:
-
比如有一个C结构体。
-
解包。通过socket.recv接收到了一个上面的结构体数据,存在字符串buffer中,现在需要把它解析出来,可以使用unpack()函数:id, name = struct.unpack("!ic", buffer)。上面的格式字符串中,!表示我们要使用网络字节顺序解析,因为我们的数据是从网络中接收到的,在网络上传送的时候它是网络字节顺序的。后面的i表示 一个int的id,c表示一个char的name。
-
打包。就通过一个unpack,现在id, name里已经保存好我们的信息了。同样,也可以很方便的把本地数据再pack成struct格式。buffer = struct.pack("!ic", id, name)。pack函数就把id, name按照指定的格式转换成了结构体,buffer 现在是一个字符串(实际上是类似于c结构体的字节流),可以通过 socket.send(buffer )把这个字符串发送出去.
END
举例理解2:
-
多数据构成。如下图
-
分析。此时的binary就是二进制形式的数据了,可以直接写入文件比如 file.write(binary)。然后,当我们需要时可以再读出来,binary=file.read()。也可以通过struct.unpack()解码成python变量,a,b,c,d=struct.unpack('5s5sif',binary),'5s5sif'这个叫做fmt,就是格式字符串,由数字加字符构成,5s表示占5个字符的字符串,i表示整数,f表示浮点数。