Python的功能模块[1] -> struct -> struct 在网络编程中的使用

struct模块 / struct Module



在网络编程中,利用 socket 进行通信时,常常会用到 struct 模块,在网络通信中,大多数传递的数据以二进制流(binary data)存在。传递字符串时无需过多担心,但传递 int,char 之类的基本数据时,就需要一种机制将某些特定的结构体类型打包成二进制流的字符串,然后在进行网络传输,而接收端也可以通过某种机制进行解包还原出原始数据。struct 模块便提供了这种机制,该模块主要作用就是对 python 基本类型值与用 python 字符串格式表示的 C struc 类型间的转化(This module performs conversions between Python values and C structs represented as Python strings.)。

另一种使用场景在与 python 与其他语言之间数据交换时使用,例如 C++ 写的客户端发送了一个 int 型(4字节)的数据到 Python 的服务器,Python 接收到这个数据时,需要解析成 Python 认识的整数,此时就将用到 struct 模块。

函数 / Function



pack()函数

函数调用: bs = struct.pack(format, *argv)

函数功能: 用于将数据按照格式打包成 bytes 形式

传入参数: format, *argv

format: str 类型,为打包的格式

*argv: 需要打包的数据,多种不同数据由 ’,’ 隔开,与 format 对应

返回参数: bs

bs: byte 类型,为打包后的二进制数据

unpack()函数

函数调用: data = struct.unpack(format, bstr)

函数功能: 用于将数据按照格式从 bytes 形式中解码出来

传入参数: format, bstr

format: str 类型,为解码的格式

bstr: byte 类型,需要解码的数据,多种不同数据由 ’,’ 隔开,与 format 对应

返回参数: data

data: tuple 类型,为解码获得的数据组

calcsize()函数

函数调用: len = struct.calcsize(format)

函数功能: 用于计算以 format 格式形成的数据占用的字节数

传入参数:  format

format: str 类型,为打包解包的格式,如 ‘H’,‘h’,‘I’ 等

返回参数: len

len: int 类型,格式化数据占用的字节数

pack_into()函数

函数调用: data = struct.pack_into(format, buffer, offset, *argv)

函数功能: 用于将数据依照 format 进行打包,以 offset 开头存入 buffer 中

传入参数: format, buffer, offset, *argv

format: str 类型,为打包解包的格式

buffer: instance 类型,可由 ctypes.create_string_buffer(size) 生成,buf.raw 查看

offset: int 类型,buffer 中的起始位数偏移

*argv: 需要处理的数据

返回参数:

pack_from()函数

函数调用: struct.pack_from(format, buffer, offset=0)

函数功能: 用于将数据以 offset 开头从 buffer 中取出,依照 format 进行格式化

传入参数: format

format: str 类型,为打包解包的格式

buffer: instance 类型,可由 ctypes.create_string_buffer(size) 生成,buf.raw 查看

offset: int 类型,buffer 中的起始位数偏移

返回参数: data

data: tuple 类型,解码出来的数据组

补充内容 / Complement



pack_into() 函数与 pack_from() 函数的使用

使用二进制打包数据的场景大部分都是对性能要求比较高的使用环境。而在上面提到的 pack 方法都是对输入数据进行操作后重新创建了一个内存空间用于返回,也就是说我们每次pack 都会在内存中分配出相应的内存资源,这有时是一种很大的性能浪费,struct 模块还提供了 pack_into() 和 unpack_from() 的方法用来解决这样的问题,也就是对一个已经提前分配好的 buffer 进行字节的填充,而不会每次都产生一个新对象对字节进行存储。对比使用 pack 方法打包,pack_into 方法一直是在buffer 对象进行操作,没有产生多余的内存浪费。另外需要注意的一点是,pack_into 和 unpack_from 方法均是对 string buffer 对象进行操作,并提供了 offset 参数,用户可以通过指定相应的 offset,使相应的处理变得更加灵活。例如,我们可以把多个对象 pack 到一个 buffer 里面,然后通过指定不同的 offset 进行 unpack。

struct类型参照表

Format

C    Type

Python    type

Standard    size

Notes

x


pad   byte


no   value


c


char


string   of length 1


1


b


signed   char


integer


1


(3)


B


unsigned   char


integer


1


(3)


?


_Bool


bool


1


(1)


h


short


integer


2


(3)


H


unsigned   short


integer


2


(3)


i


int


integer


4


(3)


I


unsigned   int


integer


4


(3)


l


long


integer


4


(3)


L


unsigned   long


integer


4


(3)


q


long   long


integer


8


(2),   (3)


Q


Unsigned   long long


integer


8


(2),   (3)


F


float


float


4


(4)


d


double


float


8


(4)


s


char[]


string


1


p


char[]


string


P


void   *


integer


(5),   (3)

Notes:

       # 以下内容由后文英文说明翻译而成,有待后续验证

1. 在 C99 中,’?’ 转换码代表 C 语言的 _bool 类型,如果不行,可以尝试 char 型模式,对应 1 个 byte;

2.6 版本新增

2. ’q’ 和 ’Q’ 转换码只有在 C 的平台编译器支持 C long long 类型,或 Windows 下才可在本地模式下使用,在标准模式下均可使用,无限制;

2.2 版本新增

3. 当尝试给 pack 一个 non-integer 非整数的类型到一个 integer 整数类型时,如果非整数类型有 __index__() 方法,则在 pack 之前会调用该方法,若没有 __index__() 方法,或者调用 __index__() 方法是出现 TypeError,则会尝试 __init__() 方法。然而,__init()__ 的使用并不被推荐,并且会产生 DeprecationWarning;

2.7 版本修改: 对 non-integer 使用 __index__() 方法为 2.7 版本新增

2.7 版本修改: 在 2.7 版本之前,并非所有的 integer 转换码会调用 __init__() 方法进行转换,且 DeprecationWarning 只会在 float 浮点型转换时产生

4. 对于 ’f’ 和 ’d’ 转换码,不论平台是什么,打包时均使用 IEEE754 二进制 32 格式(对于 ’f’ )和二进制 64 格式(对于 ’d’)

5. P 格式仅对本地字节命令可用(默认的类型或带有 ’@’ 的二进制命令字符)。二进制命令字符 ’=’ 根据主机系统的不同,使用了小端法/大端法排序,struct 不会将其解释为本地命令,为此 ’P’ 不可用。

以下为原版英文内容

1. The ‘?‘ conversion code corresponds to the _Bool type defined by C99. If this type is not available, it is simulated using a char. In standard mode, it is always represented by one byte.

New in version 2.6.

2. The ‘q‘ and ‘Q‘ conversion codes are available in native mode only if the platform C compiler supports C long long, or, on Windows, __int64. They are always available in standard modes.

New in version 2.2.

3. When attempting to pack a non-integer using any of the integer conversion codes, if the non-integer has a __index__() method then that method is called to convert the argument to an integer before packing. If no __index__() method exists, or the call to __index__() raises TypeError, then the __int__() method is tried. However, the use of __int__() is deprecated, and will raise DeprecationWarning.

Changed in version 2.7: Use of the __index__() method for non-integers is new in 2.7.

Changed in version 2.7: Prior to version 2.7, not all integer conversion codes would use the __int__() method to convert, and DeprecationWarning was raised only for float arguments.

4. For the ‘f‘ and ‘d‘ conversion codes, the packed representation uses the IEEE 754 binary32 (for ‘f‘) or binary64 (for ‘d‘) format, regardless of the floating-point format used by the platform.

5. he ‘P‘ format character is only available for the native byte ordering (selected as the default or with the ‘@‘ byte order character). The byte order character ‘=‘ chooses to use little- or big-endian ordering based on the host system. The struct module does not interpret this as native ordering, so the ‘P‘ format is not available.

A format character may be preceded by an integral repeat count. For example, the format string ‘4h‘ means exactly the same as ‘hhhh‘.

Whitespace characters between formats are ignored; a count and its format must not contain whitespace though.

For the ‘s‘ format character, the count is interpreted as the size of the string, not a repeat count like for the other format characters; for example, ‘10s‘ means a single 10-byte string, while ‘10c‘ means 10 characters. For packing, the string is truncated or padded with null bytes as appropriate to make it fit. For unpacking, the resulting string always has exactly the specified number of bytes. As a special case, ‘0s‘ means a single, empty string (while ‘0c‘ means 0 characters).

The ‘p‘ format character encodes a “Pascal string”, meaning a short variable-length string stored in a fixed number of bytes, given by the count. The first byte stored is the length of the string, or 255, whichever is smaller. The bytes of the string follow. If the string passed in to pack() is too long (longer than the count minus 1), only the leading count-1 bytes of the string are stored. If the string is shorter than count-1, it is padded with null bytes so that exactly count bytes in all are used. Note that for unpack(), the ‘p‘ format character consumes count bytes, but that the string returned can never contain more than 255 characters.

For the ‘P‘ format character, the return value is a Python integer or long integer, depending on the size needed to hold a pointer when it has been cast to an integer type. A NULL pointer will always be returned as the Python integer 0. When packing pointer-sized values, Python integer or long integer objects may be used. For example, the Alpha and Merced processors use 64-bit pointer values, meaning a Python long integer will be used to hold the pointer; other platforms use 32-bit pointers and will use a Python integer.

For the ‘?‘ format character, the return value is either True or False. When packing, the truth value of the argument object is used. Either 0 or 1 in the native or standard bool representation will be packed, and any non-zero value will be True when unpacking.

struct模块基本函数应用


 1 import struct
 2 from ctypes import create_string_buffer
 3
 4 a = 20
 5 b = 400
 6
 7 # python data --> bytes
 8 def pack():
 9     s = struct.pack(‘ii‘, a, b)
10     x = struct.pack(‘!ii‘, a, b)
11     print(‘length:‘, len(s))
12     print(‘pack without "!"‘, s)
13     print(repr(s))
14     print(‘pack with "!"‘, x)
15     return s
16
17 # bytes --> python data
18 def unpack():
19     s = struct.unpack(‘ii‘, struct.pack(‘ii‘, a, b))
20     x = struct.unpack(‘!ii‘, struct.pack(‘ii‘, a, b))
21     print(‘length:‘, len(s))
22     print(‘pack without "!"‘, s)
23     print(repr(s))
24     print(‘pack with "!"‘, x)
25     return s
26
27 # calculate the size of corrsponding format
28 def cal():
29     print("len: ", struct.calcsize(‘i‘))       # len:  4
30     print("len: ", struct.calcsize(‘ii‘))      # len:  8
31     print("len: ", struct.calcsize(‘f‘))       # len:  4
32     print("len: ", struct.calcsize(‘ff‘))      # len:  8
33     print("len: ", struct.calcsize(‘s‘))       # len:  1
34     print("len: ", struct.calcsize(‘ss‘))      # len:  2
35     print("len: ", struct.calcsize(‘d‘))       # len:  8
36     print("len: ", struct.calcsize(‘dd‘))      # len:  16
37
38 def _into():
39     buf = create_string_buffer(12)
40     # ‘\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00‘
41     print(repr(buf.raw))
42     print(struct.pack_into("iii", buf, 0, 1, 2, -1))
43
44 def _from():
45     buf = create_string_buffer(12)
46     # ‘\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00‘
47     print(repr(buf.raw))
48     print(struct.unpack_from("iii", buf, 0))
49
50 pack()
51 unpack()
52 cal()
53 _into()
54 _from()

Note: 当 format 为 ’ii’ 时,需要 2 个参数,当为 ’2i’ 时,只需要 1 个。

参考链接



http://blog.csdn.net/ithomer/article/details/5974029

http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html

原文地址:https://www.cnblogs.com/stacklike/p/8116580.html

时间: 2024-10-14 09:06:29

Python的功能模块[1] -> struct -> struct 在网络编程中的使用的相关文章

Python基础教程(第十四章 网络编程)

本文内容全部出自<Python基础教程>第二版,在此分享自己的学习之路. ______欢迎转载:http://www.cnblogs.com/Marlowes/p/5538341.html______ Created on Marlowes 本章将会给读者展示一些例子,这些例子会使用多种Python的方法编写一个将网络(比如因特网)作为重要组成部分的程序.Python是一个很强大的网络编程工具,这么说有很多原因,首先,Python内有很多针对常见网络协议的库,在库顶部可以获得抽象层,这样就可以

python基础教程_学习笔记24:网络编程、Python和万维网

网络编程 python是一个很强大的网络编程工具,首先,它有很多针对常见网络协议的库,在库顶部可以获得抽象层,这样可以集中精力在程序的逻辑处理上,而不是停留在网络实现的细节上:其次,python处理字节流的各种模式方面很擅长,因此可以轻松处理各种协议格式. 少数几个网络设计模块 socket模块 在网络编程中的一个基本组件就是套接字(socket).套接字主要是两个程序之间"信息通道".程序可能(通过网络连接)分布在不同的计算机上,通过套接字相互发送信息.在Python中的大多数的网络

Python之路(十四):网络编程基础

Python基础之网络编程 学习网络编程之前,要对计算机底层的通信实现机制要有一定的理解. OSI 互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层 可以将应用层,表示层,会话层并作应用层,从tcp/ip五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议 就理解了整个互联网通信的原理. 首先,用户感知到的只是最上面一层应用层,自上而下每层都依赖于下一层,所以我们从最下一层开始切入,比较好理解 每层都运行特定的协议,越往上越靠近用户,越往下越靠近硬件. 物理层 物

Python开发【第八篇】:网络编程 Socket

Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用[打开][读写][关闭]模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: file模块是针对某个指定

Python开发【第八篇】:网络编程

Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: fil

&lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第14章 | 网络编程

Python是个很强大的网络编程工具,原因有二: 1. Python内有很多针对常见网络协议的库 2. Python在处理字节流方面的优势 本章主要内容: 探讨Python标准库中的一些网络模块,探讨SocketServer类,最后是Twisted框架. ------ 相关模块 Socket模块 基本组件,用于两个程序之间的信息通道.套接字包括两个: 服务器套接字和客户端套接字.创建一个服务器套接字后,让它等待连接,这样它就在某个网络地址处监听.客户端套接字负责:简单的连接,完成事务,断开连接.

Python开发【第*篇】【Socket网络编程】

1.Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作. socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别:

Python自动化开发课堂笔记【Day08】 - Python进阶(面向对象的高级用法,网络编程)

面向对象的高级用法 1. __str__ 只要执行打印对象的操作,就会触发该对象类中的__str__方法(也就是对象的绑定方法)它是一种默认的方法,默认的打印输出为<__main__.Foo object at 0x003EE350>,但是如果将该绑定方法在类中重写的话,要求必须有以字符串类型的返回值,返回形式可以自己设定. class Foo: def __init__(self,name,age): self.name = name self.age = age def __str__(s

Python Socket,How to Create Socket Server? - 网络编程实例

文章出自:Python socket – network programming tutorial by Silver Moon 原创译文,如有版权问题请联系删除. Network programing in Python: Part2: Programing sockets servers. 在所有的通信实例中,都分为Client 和Server. 其中:Client是请求的发起点,Server是使用Socket接收传入的值并且提供返回数据. Server的职能如下: 1>.创建/打开一个so