struct
模块提供了一种处理二进制数据的方式struct.pack(fmt, v1, v2......)
作用:
格式化表格来自于官网:struct — Interpret bytes as packed binary data — Python 3.12.1 documentation
Format | C Type | Python type | Standard size | Notes |
---|---|---|---|---|
x | pad byte | no value | (7) | |
c | char | bytes of length 1 | 1 | |
b | signed char | integer | 1 | (1), (2) |
B | unsigned char | integer | 1 | (2) |
? | _Bool | bool | 1 | (1) |
h | short | integer | 2 | (2) |
H | unsigned short | integer | 2 | (2) |
i | int | integer | 4 | (2) |
I | unsigned int | integer | 4 | (2) |
l | long | integer | 4 | (2) |
L | unsigned long | integer | 4 | (2) |
q | long long | integer | 8 | (2) |
Q | unsigned long long | integer | 8 | (2) |
n | ssize_t | integer | (3) | |
N | size_t | integer | (3) | |
e | (6) | float | 2 | (4) |
f | float | float | 4 | (4) |
d | double | float | 8 | (4) |
s | char[] | bytes | (9) | |
p | char[] | bytes | (8) | |
P | void* | integer | (5) |
import struct
int_value = 123156456
float_value = 4561.1123
bool_value = True
# 整型打包以后占用四个字节
int_struct = struct.pack('i', int_value)
print(int_struct, len(int_struct))
# 浮点型打包以后占用四个字节
float_struct = struct.pack('f', float_value)
print(float_struct, len(float_struct))
# 布尔型打包以后占用四个字节
bool_struct = struct.pack('?', bool_value)
print(bool_struct, len(bool_struct))
import struct
str_value = "da456q1"
# 字符串格式需要转换成字节格式才可以打包,并且还需要提供字符串的长度,默认为1
# 提供的长度小于实际字符串的长度将打包部分数据,造成打包不完整
str_struct = struct.pack('7s', str_value.encode("utf8"))
print(str_struct, len(str_struct))
import struct
int_value = 123156456
float_value = 4561.1123
bool_value = True
str_value = "da456q1"
# 一次打包多个
all_struct = struct.pack('i f ? 2s', int_value, float_value, bool_value, str_value.encode("utf8"))
print(all_struct, len(all_struct))
struct.unpack(fmt, v1, v2......)
import struct
int_struct = struct.pack('i', 123156456)
float_struct = struct.pack('f', 4561.1123)
bool_struct = struct.pack('?', True)
str_struct = struct.pack('7s', "da456q1".encode("utf8"))
# 解包后类型正常
int_res = struct.unpack("i", int_struct)
print(int_res, type(int_res[0]))
float_res = struct.unpack("f", float_struct)
print(float_res, type(float_res[0]))
bool_res = struct.unpack("?", bool_struct)
print(bool_res, type(bool_res[0]))
str_res = struct.unpack("7s", str_struct)
print(str_res, type(str_res[0]))
import struct
int_value = 123156456
float_value = 4561.1123
bool_value = True
str_value = "da456q1"
all_struct = struct.pack('i f ? 7s', int_value, float_value, bool_value, str_value.encode("utf8"))
res = struct.unpack('i f ? 7s', all_struct)
print(res)
# (123156456, 4561.1123046875, True, b'da456q1')
问题:
在socket模块的TCP协议传输数据中
由于接收方不知道将要收到多大的数据,而导致数据读取可能不完整
出现粘包问题,struct模块就可以用来解决这个问题
解决办法:
# 服务端
import socket
import struct
# 1320KB的数据内容
big_data = ("重要信息" * 110).encode("utf8")
data_size = len(big_data)
data_size_struct = struct.pack("i", data_size)
# 创建socket对象
server = socket.socket()
server.bind(("localhost", 5656))
server.listen()
conn, addr = server.accept()
# 先发送大小数据
conn.send(data_size_struct)
# 发送大数据包
conn.send(big_data)
# 关闭
conn.close()
server.close()
# 客户端
import socket
import struct
client = socket.socket()
client.connect(("localhost", 5656))
# 读取大小文件
head = client.recv(4)
total = struct.unpack("i", head)[0]
# 根据大小接收数据
have = 0
data = bytes()
while have < total:
data += client.recv(1024)
have += 1024
print(data.decode("utf8"))
client.close()