struct 模块
1. Struct 简介
2. Struct 代码示例
1. Struct 简介
当 python 需要通过网络与其他的平台进行交互的时候,必须考虑到将这些数据类型与其他平台或语言之间的类型进行互相转换问题。打个比方:C++ 写的客户端发送一个 int 型(4 字节)变量的数据到 python 写的服务器,python 接收到表示这个整数的 4 个字节数据,怎么解析成 python 认识的整数呢?python 的标准模块 struct 就用来解决这个问题。
格式符
在 python 手册中,给出了 C 语言中常用类型与 python 类型对应的格式符:
格式符 |
C语言类型 |
Python类型 |
x |
pad byte |
no value |
c |
char |
string of length 1 |
b |
signed char |
integer |
B |
unsigned char |
integer |
? |
_Bool |
bool |
h |
short |
integer |
H |
unsigned short |
integer |
i |
int |
integer |
I |
unsigned int |
integer or long |
l |
long |
integer |
L |
unsigned long |
long |
q |
long long |
long |
Q |
unsigned long long |
long |
f |
float |
float |
d |
double |
float |
s |
char[] |
string |
p |
char[] |
string |
P |
void * |
long |
2. Struct 代码示例
2.1 struct.pack
struct.pack 用于将 python 值(各种数据类型),根据格式符转换为 bytes(字节)类型。
函数原型为:struct.pack(fmt, v1, v2, ...),参数 fmt 是格式字符串;v1, v2, ... 表示要转换的 python 数据。
示例 1:将两个整数转换为 bytes(字节)类型
格式符"i"表示转换为 int,"ii"表示有两个 int 变量。进行转换后的结果长度为 8 个字节(int 类型占用 4 个字节,两个 int 为 8 个字节),可以看到输出的结果是二进制数据。
1 import struct
2
3 a = 20
4 b = 400
5
6 # 转换后的bytes_str为bytes(字节)类型,可以在网络上传输
7 bytes_str = struct.pack("ii", a, b) # 也可以用"2i"表示
8
9 print("length: ", len(bytes_str)) # 8
10 print(bytes_str) # b'\x14\x00\x00\x00\x90\x01\x00\x00'
11 print(type(bytes_str)) # <class 'bytes'>
示例 2:将字符串和整数转换为 bytes(字节)类型
1 import struct
2
3 a = b"abc123"
4 b = "嘻哈".encode("utf-8")
5 c = 12
6
7 bytes_str = struct.pack("5s7si", a, b, c) # argument for 's' must be a bytes object
8 a1, a2, a3 = struct.unpack("5s7si", bytes_str)
9
10 print(a1, a2, a3) # b'abc12' b'\xe5\x98\xbb\xe5\x93\x88\x00' 12
11 # 注意:对于s,转换的多余长度会用\x00补齐
2.2 struct.unpack
struct.unpack 做的工作刚好与 struct.pack 相反,用于将字节类型的数据转换成 python 数据。
函数原型为:struct.unpack(fmt, string),返回的是一个元组。
1 import struct
2
3 a, b = 20, 400
4
5 bytes_str = struct.pack("ii", a, b)
6 a1, a2 = struct.unpack("2i", bytes_str)
7 print(a1, a2) # 20 400
8
9 # 注意只unpack一个值时的取法
10 bytes_c = struct.pack("i", a)
11 c, = struct.unpack("i", bytes_c)
12 print(c) # 20
13 d = struct.unpack("i", bytes_c)
14 print(d) # (20,)
2.3 struct.calcsize
struct.calcsize 用于计算格式字符串所对应的结果的长度,如:struct.calcsize('ii') 返回 8。因为两个 int 类型所占用的长度是 8 个字节。
1 >>> struct.calcsize("19s") + struct.calcsize("i")
2 23
3 >>> struct.calcsize("i19s")
4 23
5 >>> struct.calcsize("19si")
6 24
问:为什么"19si"的结果不是 23 呢?
任何特定类型(字节、整数等)只能从其标准尺寸的倍数的偏移开始。
字节串 s 可以从任何偏移量开始,因为它的标准大小为 1,但是 32 位整数只能以 4 的倍数(它的大小)偏移量开始,例如 0、4、8、12 等,因此必须填充若干个字节以允许整数处于适当的偏移量。
示例:Python 写的服务器端与 C 写的客户端的通信
Python 写的服务器端:
1 import socket, struct
2
3 s = socket.socket()
4 s.bind(('127.0.0.1', 8000))
5 s.listen(1)
6
7 try:
8 while True:
9 cli, addr = s.accept()
10 data = cli.recv(100)
11
12 print("recv %d bytes" % len(data))
13 a, b, c = struct.unpack('i10sh', data)
14 print(a, b, c)
15 # i表示int, 10s表示10个char类型, h表示short int
16 sdata = struct.pack('i10sh', 34, b"abcdefghi", 65)
17 cli.send(sdata)
18 finally:
19 s.close()
C 写的客户端:
1 /* tcp_client.c */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9 #include <unistd.h>
10
11 typedef struct _data {
12 int a;
13 char b[10];
14 short c;
15 } Data;
16
17 int main()
18 {
19 int client_fd;
20 struct sockaddr_in server_addr;
21
22 server_addr.sin_family = AF_INET;
23 server_addr.sin_port = htons(8000);
24 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
25 bzero(&(server_addr.sin_zero), 8);
26
27 client_fd = socket(AF_INET, SOCK_STREAM, 0);
28
29 connect(client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
30
31 Data d;
32 memset(&d, 0, sizeof(d));
33 d.a = 3;
34 memcpy(&d.b, "hello", 5);
35 d.c = 6;
36 send(client_fd, &d, sizeof(d), 0);
37
38 char buf[200];
39 bzero(buf, 200);
40 recv(client_fd, buf, sizeof(buf), 0);
41
42 Data* p = (Data*)&buf;
43 printf("%d %s %d\n", p->a, p->b, p->c);
44
45 close(client_fd);
46
47 return 0;
48 }
struct 模块的更多相关文章
- 字节流与数据类型的相互转换---使用struct模块
字节流与数据类型的相互转换---使用struct模块 http://blog.csdn.net/Sunboy_2050/article/details/5974029 Python是一门非常简洁的语言 ...
- Python学习——struct模块的pack、unpack示例
he struct module includes functions for converting between strings of bytes and native Python data t ...
- c语言write与python的struct模块交互
以下讲的都是用二进制形式打开文件.网上有很多struct模块的文章,下面是我做的小实验. 1.对于c里面的fwrite写入一个单字节,写的就是它的二进制.如3,写入文件就是二进制0x03,它并不是3的 ...
- python中struct模块及packet和unpacket
转自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 我们知道python只定义了6种数据类型,字符串,整数,浮点数,列表,元组 ...
- 浅析Python中的struct模块
最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结. 了解c语言 ...
- 2、粘包现象(struct模块)
昨天我们所做的套接字是有漏洞的,它会出现粘包现象,没有发现这个问题的我们今天会进行演示.今天也会稍微讲解一下基于udp的套接字. 一.基于udp的套接字 udp是无链接的,先启动哪一端都不会报错 ud ...
- Python struct模块
有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重 ...
- python中的struct模块的学习
由于TCP协议中的黏包现象的发生,对于最low的办法,每次发送之前让他睡一秒,然后在发送,可是这样真的太low了,而且太占用资源了. 黏包现象只发生在tcp协议中: 1.从表面上看,黏包问题主要是因为 ...
- python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- 【转】浅析Python中的struct模块
[转]浅析Python中的struct模块 最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概 ...
随机推荐
- CSS实现页面切换时的滑动效果
最近在开发手机端APP页面功能时遇到一个需求:某个页面查询的数据有三种分类,需要展示在同一页面上,用户通过点击分类标签来查看不同类型的数据, 期望效果是 用户点击标签切换时另一个页面能够以一个平滑切入 ...
- go语言-csp模型-并发通道
[前言]go语言的并发机制以及它所使用的CSP并发模型 一.CSP并发模型 CSP模型是上个世纪七十年代提出的,用于描述两个独立的并发实体通过共享的通讯 channel(管道)进行通信的并发模型. C ...
- 从头捋了一遍 Java 代理机制,收获颇丰
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...
- 2.2 Python3基础-基本数据类型
>>返回主目录 源代码 # 基本数据类型 # Number类型:如何查看变量的数据类型? name = 'Portos' print(type(name)) # 结果:str print( ...
- Python3基础-目录
Python3基础-目录(Tips:长期更新Python3目录) 第一章 初识Python3 1.1 Python3基础-前言 1.2 Python3基础-规范 第二章 Python3内置函数&a ...
- 面试现场:说说char 和 varchar的区别你了解多少?
Hi,大家好!我是白日梦!本文是MySQL专题的第 26 篇. 下文还是白日梦以自导自演的方式,围绕"说说char 和 varchar的区别你了解多少?"展开本话题.看看你能抗到第 ...
- Django的路由控制
一.Django中路由到作用 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来 ...
- 前端性能监控之performance
如果我们想要对一个网页进行性能监控,那么使用window.performance是一个比较好的选择. 我们通过window.performance可以获取到用户访问一个页面的每个阶段的精确时间,从而对 ...
- 聊一聊桥接(JSBridge)的原理
一.前言 如今的互联网时代也称移动互联网时代,基本上每个人每天都会花费大量时间在移动设备上,早期的移动端应用大都使用原生开发(android,ios),而现在的移动开发技术选型上基本都是混合开发(Hy ...
- [源码解析] 并行分布式框架 Celery 之架构 (2)
[源码解析] 并行分布式框架 Celery 之架构 (2) 目录 [源码解析] 并行分布式框架 Celery 之架构 (2) 0x00 摘要 0x01 上文回顾 0x02 worker的思考 2.1 ...