Python的struct打包通讯数据头文件
总目录
一、struct函数介绍
在Python中,struct
模块提供了打包和解包原始数据类型(如整型、浮点数等)为字节对象的函数。这对于处理二进制数据,特别是与C语言库接口或网络协议交互时非常有用,因为它们经常需要以特定的字节顺序(字节对齐)来表示数据。
二、打包和解包
(一)打包
import struct
# 打包一个整型和浮点数
packed_data = struct.pack('if', 1234, 56.78)
(二)解包
# 解包上面打包的数据
unpacked_data = struct.unpack('if', packed_data)
(三)总结使用方法:
打包与解包,函数中的第一个参数要一至,具体该参数如何设置,请看下面内容:
需要说明的地方:
格式字符串
格式字符串指定了数据的类型和字节顺序。它由一个或多个格式字符组成,每个字符对应一个值。
x
: 填充字节c
: 字符b
: 有符号字节B
: 无符号字节?
: 布尔值h
: 有符号短整型(16位,2字节)H
: 无符号短整型i
: 有符号整型(32位,4字节)I
: 无符号整型l
: 有符号长整型(32位,4字节)L
: 无符号长整型q
: 有符号长长整型(64位,8字节)Q
: 无符号长长整型f
: 单精度浮点数(32位,4字节)d
: 双精度浮点数(64位,8字节)s
: 字符串(字节串)p
: Pascal字符串
字节顺序、对齐
可以在格式字符串前加上字节顺序和对齐信息:
@
: 原生字节顺序和对齐(默认)<
: 小端字节顺序,无填充>
: 大端字节顺序,无填充!
: 网络字节顺序(大端),无填充=
: 原生字节顺序,但使用标准C类型填充
三、具体用法举例:
在使用TCP和UDP等数据传输时,可以使用下列方法“夹带私货”。
发送数据前,将头文件head与需要传输的其他数据message进行连接,head打包后就是二进制数据,message需要使用message.encode()进行编码。
收到数据后,将头文件head与其他的传输数据message的二进制数据,使用切片的方法进行分开,分别进行解包和解码
(一)传送ip地址
import sturct
#==================#
# ip地址通过头传递 #
#==================#
dest_ip = '192.168.0.1'
#将ip地址,依据'.'作为分节符,转换为字符串列表
list = dest_ip.split('.')
#打包头文件
head = struct.pack('!hhhh',int(list[0]),int(list[1]),int(list[2]),int(list[3]))
print(head[:8])
#假如还有其他数据进行传输
message = '你好'
#待发送的数据
send_data = head + message.encode()
#==================数据发送和接收部分省略===============
recv_data = send_data
#数据切片,获得head头文件和message_data
head = recv_data[:8]
message_data = recv_data[8:]
#从head获得ip地址
ip_list = struct.unpack('!hhhh',head))
print(ip_list[0] + '.' + ip_list[1] + '.' + ip_list[2] + '.' + ip_list[3])
#获取message
message = message_data.decode()
(二)通过头文件传递时间戳
import struct
import time
#==================#
# 时间戳通过头传递 #
#==================#
#为了减小传输内容,截取时间戳的后6位数,生成间隔1秒的两个时间戳
a = int(time.time()*1000)-int(time.time()/1000)*1000000
time.sleep(1)
b = int(time.time()*1000)-int(time.time()/1000)*1000000
print(a,b)
#打包头文件
head_a = struct.pack('!l',a)
head_b = struct.pack('!l',b)
#========传输过程中,切片获得头文件是[:4]这里不再赘述==========
#解包头文件
print(struct.unpack('!l',head_a)[0])
print(struct.unpack('!l',head_b)[0])
(三)传输一个数字字符串作为通讯标志
import struct
#=================#
# 用一个数字字符串传输标志 #
#=================#
a = 1
head = struct.pack('!l', a)
print(head)
print(head[:4]) #数据切片也是[:4],可以正好获得head数据
arg = struct.unpack('!l', head[:4])
print(arg[0])