This commit is contained in:
田岩
2025-12-02 21:04:46 +08:00
parent fee7149458
commit 73a3d2e914
68 changed files with 1712 additions and 234 deletions
@@ -5,7 +5,7 @@ import gzip
from typing import Optional, Union, Dict, Any, List, Tuple
# -------------------------- 协议常量定义(与JS完全一致) --------------------------
# -------------------------- 协议常量定义 --------------------------
class ProtocolConst:
PROTOCOL_VERSION = 0b0001 # 协议版本(4位,字节0低4位,0~15)
HEADER_SIZE = 8 # 头部固定字节数(字节0~7
@@ -13,13 +13,13 @@ class ProtocolConst:
STRING_ENCODING = "utf-8" # 字符串默认编码
# -------------------------- 枚举定义(与JS码值完全对齐) --------------------------
# -------------------------- 枚举定义 --------------------------
class MessageType(IntEnum):
"""消息类型(4位,字节0高4位,0~15)"""
PING = 0b0001 # 心跳(支持空包体)
AUDIO_DATA = 0b0010 # 纯音频数据(pcm)
TEXT_MESSAGE = 0b0011 # 纯文本消息
CONTROL_CMD = 0b0100 # 控制指令(暂停/继续等)
CONTROL_CMD = 0b0100 # 控制指令
# 预留12种类型(0b0100 ~ 0b1111
@@ -161,11 +161,11 @@ class ProtocolCodec:
return header + compressed_body
@staticmethod
def unpack(packet: bytes) -> Tuple[MessageType, SerializationType, CompressionType, int, Any]:
def unpack(packet: bytes) -> Tuple[MessageType, int, Any]:
"""
解析协议包与JS unpack 方法完全兼容
:param packet: 完整协议包头部 + 包体
:return: (消息类型, 序列化方式, 压缩方式, 顺序号, 原始包体数据)
:return: (消息类型, 顺序号, 原始包体数据) # 仅返回核心必要信息
"""
# 1. 校验包长度
if len(packet) < ProtocolConst.HEADER_SIZE:
@@ -193,7 +193,7 @@ class ProtocolCodec:
# 字节4~6:包体长度(24位大端序),字节7:保留位(忽略)
body_len = (header[4] << 16) | (header[5] << 8) | header[6]
# 校验版本和包体长度
# 校验版本和包体长度(校验逻辑保留,确保数据有效性)
if version != ProtocolConst.PROTOCOL_VERSION:
raise ValueError(
f"协议版本不匹配:收到v{version}0b{version:04b}),支持v{ProtocolConst.PROTOCOL_VERSION}0b{ProtocolConst.PROTOCOL_VERSION:04b}"
@@ -236,16 +236,17 @@ class ProtocolCodec:
else:
raise ValueError(f"不支持的序列化方式:{serialization}")
return msg_type, serialization, compression, sequence, original_body
# 仅返回核心必要信息:消息类型、顺序号、原始包体数据
return msg_type, sequence, original_body
# -------------------------- 使用示例(验证与JS兼容性 --------------------------
# -------------------------- 使用示例(验证修改后功能正常 --------------------------
if __name__ == "__main__":
# 示例1:PING消息(空包体,默认顺序号0)
ping_packet = ProtocolCodec.pack(MessageType.PING)
print(f"PING消息包长度:{len(ping_packet)}字节(仅头部)")
msg_type1, ser1, comp1, seq1, body1 = ProtocolCodec.unpack(ping_packet)
print(f"PING解析结果:类型={msg_type1.name}序列化={ser1.name},压缩={comp1.name}顺序号={seq1},包体={body1}\n")
msg_type1, seq1, body1 = ProtocolCodec.unpack(ping_packet)
print(f"PING解析结果:类型={msg_type1.name},顺序号={seq1},包体={body1}\n")
# 示例2:纯文本消息(STRING序列化,指定顺序号)
text_body = "Python与JS协议兼容测试(纯字符串)"
@@ -256,8 +257,8 @@ if __name__ == "__main__":
compression=CompressionType.NONE
)
print(f"文本消息包长度:{len(text_packet)}字节")
msg_type2, ser2, comp2, seq2, body2 = ProtocolCodec.unpack(text_packet)
print(f"文本解析结果:类型={msg_type2.name}序列化={ser2.name}顺序号={seq2},内容={body2}\n")
msg_type2, seq2, body2 = ProtocolCodec.unpack(text_packet)
print(f"文本解析结果:类型={msg_type2.name},顺序号={seq2},内容={body2}\n")
# 示例3:控制指令(JSON序列化)
control_body = {"cmd": ControlCommand.PAUSE.value, "reason": "用户主动暂停"}
@@ -267,8 +268,8 @@ if __name__ == "__main__":
sequence=1002
)
print(f"控制指令包长度:{len(control_packet)}字节")
msg_type3, ser3, comp3, seq3, body3 = ProtocolCodec.unpack(control_packet)
print(f"控制指令解析结果:类型={msg_type3.name}序列化={ser3.name}顺序号={seq3},内容={body3}\n")
msg_type3, seq3, body3 = ProtocolCodec.unpack(control_packet)
print(f"控制指令解析结果:类型={msg_type3.name},顺序号={seq3},内容={body3}\n")
# 示例4:音频数据(RAW序列化)
audio_body = b"\x00\x01\x02\x03\x04\x05" * 100 # 模拟PCM数据
@@ -278,8 +279,8 @@ if __name__ == "__main__":
sequence=1003
)
print(f"音频数据包长度:{len(audio_packet)}字节")
msg_type4, ser4, comp4, seq4, body4 = ProtocolCodec.unpack(audio_packet)
print(f"音频解析结果:类型={msg_type4.name}序列化={ser4.name}顺序号={seq4},数据长度={len(body4)}字节\n")
msg_type4, seq4, body4 = ProtocolCodec.unpack(audio_packet)
print(f"音频解析结果:类型={msg_type4.name},顺序号={seq4},数据长度={len(body4)}字节\n")
# 示例5:GZIP压缩测试(需JS端启用GZIP解压)
long_text_body = "这是一段很长的文本,用于测试GZIP压缩效果" * 100
@@ -290,5 +291,5 @@ if __name__ == "__main__":
compression=CompressionType.GZIP
)
print(f"GZIP压缩后包长度:{len(gzip_packet)}字节(原始文本长度:{len(long_text_body.encode())}字节)")
msg_type5, ser5, comp5, seq5, body5 = ProtocolCodec.unpack(gzip_packet)
print(f"GZIP解析结果:类型={msg_type5.name}压缩={comp5.name},内容前50字:{body5[:50]}...")
msg_type5, seq5, body5 = ProtocolCodec.unpack(gzip_packet)
print(f"GZIP解析结果:类型={msg_type5.name}顺序号={seq5},内容前50字:{body5[:50]}...")
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.