长度前缀分帧与粘包拆包练习
前置:理解字节流、字节序、客户端与服务端;Python 3.10+ 用于四字节长度前缀解码模型,不要求真实网络。教学范围为TCP RFC9293;分层与字节流;Python 3.10+。核对日期2026-10-17。示例未执行,本轮没有安装依赖、生成协议代码、启动服务或浏览器预览。完整源码和输入文件见下方「同源完整文件」;推演结论只适用于写明的模型。
完整长度前缀解码器
缓存循环每次只消费完整的一帧,之后立即检查是否还有下一帧。等待头部和等待负载是不同状态;超长声明应在读出长度后立即拒绝,不能先尝试分配声明大小的内存。
查看图表代码
完整长度前缀解码器接收离线十六进制分块并维护缓存,头部不足四字节时等待,负载足够才消费整帧。结束时剩余字节表示截断,超过1024字节的声明提前拒绝,避免恶意长度让接收端无限保留内存。
分帧手推预期
分帧手推预期中大端头00000003代表三个字节,负载616263解为abc。切成0000和0003616263仍得到同一消息;中文“你”占三个UTF-8字节。有效头00000000允许空消息,非法UTF-8应独立报错。
粘包拆包练习
粘包拆包练习把两帧合成一块,再从第二帧头部中间拆开,检查每次消费后残余缓存。增加消息长度上限可以限制单帧,但若把所有输入一次性读入内存,仍存在整体输入规模问题;这里的离线工具不假装生产流式服务器。
同源完整文件
以下README含前置、输入、读者自跑步骤、预期结果、失败、恢复与清理;只做静态核对,没有执行。
model.py
python
import json
import sys
def decode(chunks):
buffer = bytearray()
messages = []
for chunk in chunks:
if not isinstance(chunk, str):
raise ValueError('hex strings required')
buffer.extend(bytes.fromhex(chunk))
while len(buffer) >= 4:
size = int.from_bytes(buffer[:4], 'big')
if size > 1024:
raise ValueError('frame too large')
if len(buffer) < 4 + size:
break
messages.append(bytes(buffer[4:4 + size]).decode('utf-8'))
del buffer[:4 + size]
if buffer:
raise ValueError('truncated frame')
return messages
if __name__ == '__main__':
try:
data = json.load(sys.stdin)
if not isinstance(data, list):
raise ValueError('array of hex chunks required')
print(json.dumps(decode(data), ensure_ascii=False))
except (ValueError, TypeError) as error:
print(str(error), file=sys.stderr)
sys.exit(2)requirements.txt
text
# Python 3.10+ standard library only; no third-party dependency.README.md
md
# 计算机网络原理:完整示例
示例未执行。核对日期2026-10-17。教学版本族:TCP RFC9293;分层与字节流;Python 3.10+。
## 文件与依赖
文件:model.py, requirements.txt。requirements.txt为同源依赖声明;所有代码和配置都随本文展示。本例使用 Python 3.10+ 标准库,无额外运行依赖。
## 输入与前置
前置:理解字节流、十六进制字节和四字节大端长度头。使用 Python 3.10+,只依赖标准库;输入是表示分块字节流的十六进制字符串数组,不建立真实 TCP 连接。具体输入和分帧预期见下节。
读者将来自跑(本轮未执行):在本目录以Python 3.10+读取input.json,PowerShell示意`Get-Content -Raw input.json | python model.py`;Bash示意`python3 model.py < input.json`。把下面输入手工保存为UTF-8文件,输出按预期逐项比较。无需安装依赖,没有服务或网络调用;程序只读标准输入并写标准输出,不改原文件。失败信息写标准错误且退出2。恢复是修正输入后重读,清理只删除自己创建的input.json与输出文件,勿递归删除工作目录。
## 预期结果、失败与恢复
输入 ["0000","0003616263"],预期["abc"];["00000000"]得到[""];["0000000361"]退出2并报告truncated frame;["00000401"]报告frame too large。
失败要保留输入和错误,先与正文的不变量及边界核对。没有真实服务或性能验证,不以这些模型输出证明生产可用性。
## 独立练习
解码00000001610000000162;把分界改在第二帧头部第三字节后,再说明结束时缓存应有多少字节。
参考答案:先读第一帧长度1、负载61得a,消费5字节;第二帧头部不完整时保留3字节,下一块补齐长度和62后得b,全部结束缓存为0。未补齐就结束应报截断,不能把缓存静默丢弃。先作答,再核对
解码00000001610000000162;把分界改在第二帧头部第三字节后,再说明结束时缓存应有多少字节。
逐步参考解答
先读第一帧长度1、负载61得a,消费5字节;第二帧头部不完整时保留3字节,下一块补齐长度和62后得b,全部结束缓存为0。未补齐就结束应报截断,不能把缓存静默丢弃。
来源与适用边界
- 英文官方、作者或规范原文:本专题机制依据;按上述固定版本族阅读。
- 中文官方或作者资料:用于术语和讲解交叉核对,冲突以原始规范为准。
继续阅读
- 层次与端到端机制
- 故障边界与规范
- 故障边界与规范