背景
- 因为websocket请求/返回均需要处理字节流
- 现返回基本能正常处理,但请求字段及加密方式与业务紧密相关,抓着开发大佬问了几遍,有点头疼
Python 中的 struct 模块
pack 操作
- Pack 操作必须接受一个 template string 以及需要进行 pack 一组数据,这就意味着 pack 处理操作 定长 的数据
import struct
a = struct.pack("2I3sI", 12, 34, b"abc", 56)
print('a:',a)
#输出
a: b'\x0c\x00\x00\x00"\x00\x00\x00abc\x008\x00\x00\x00'
unpack 操作
- 对于 unpack 而言,需要 fmt 对应的字节数和字节字符串 string 的字节数一致,就可以成功的进行解析,否则 unpack 函数将抛出异常。
import struct
import binascii
packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print('Unpacked Values:', unpacked_data)
计算字节大小
print struct.calcsize("2I3sI") # 16
Python pack 操作支持的数据类型
实际处理demo(需要先处理数据长度):
import struct
###打开文件
f = open('/Users/mac_bigsur/Downloads/test_data_0x7414_12251', 'rb')
###读固定前20个字节
packed_data20 = f.read(20)
print(packed_data20)
###设置解析格式并解析
s20= struct.Struct('B B B B H H I I I')
unpacked_data20 = s20.unpack(packed_data20)
print('Unpacked Values:', unpacked_data20)
###拿到数据长度
data_len = unpacked_data20[8]
print(data_len)
###设置数据解析格式并解析
data_s = struct.Struct(str(int(data_len/4))+"I")
packed_data = f.read()
data = data_s.unpack(packed_data)
print('data',data)
- header为固定前20个字节,第9个组为body长度
- 拿到body字节长度计算后,再解析body
对应JAVA实现:
PacketByteConversion conversion = new PacketByteConversion(data);
try {
final byte flag = conversion.readByte();
final byte version = conversion.readByte();
final byte keyType = conversion.readByte();
final byte reserved = conversion.readByte();
final short cmdID = conversion.readShort();
final short seq = conversion.readShort();
final int fromID = conversion.readInt();
final int toID = conversion.readInt();
final byte unzip = 1;
int dataLen = conversion.readInt();
byte[] dataBuf = conversion.readData(dataLen);
String cmd = String.format("0x%x", cmdID);
}
参考:
https://pymotw.com/3/struct/index.html
https://blog.csdn.net/qq_37674086/article/details/118914471