“采用两字节大端长度头,这次限定载荷至多3字节,最大编码帧 M=5。给连接9字节预算,计“已完成但未消费帧的编码大小 + 当前帧预留”,不另存无界读取批次。开始读新头以前预留5;读取限制在当前…”
形式陈述
TCP字节流理路TCP字节流、序号与累计确认TCP byte stream · Cumulative ACK · TCP sequence number逐字节计算序号、累计ACK与重复重组,处理32位绕回和短读,区分对端TCP接收与应用执行。没有应用消息边界。本页固定一个小格式:每帧先放两字节无符号大端理路字节序与多字节值Byte order · Endianness · Little endian · Big endian把内存地址顺序与字节的数值权重分开,按指定端序组装整数并定位跨格式误读。长度
状态分为Header(h)、Body(L,p)、Error。h是已收但不足两字节的头,p是已收但不足L字节的载荷。初态Header(空)。每批输入按游标消费:先补满头,检查L≤16再进入Body;补满载荷便输出一帧并回到空Header,继续处理本批剩余字节。L=0立即输出空帧,不等待下一个字节。Error为本次解析的终态,不能跳过未知字节随意找下一个“看起来合法的头”。
接口区分“这次暂时没有字节”与真实EOF。对有序EOF,若处于空Header,字节格式在帧边界结束;若头只有1字节或载荷未满,则报告截断。格式合法结束仍不保证业务协议已完成,例如本来必须有一个响应但对方直接关闭。
解析不变量是:已消费的输入恰由已经输出的完整帧编码,加上当前未完成头或当前头及部分载荷组成;未消费输入保持原序。只有长度检查通过且载荷完整,才能产生一份输出。这确保任意合法短读切分都得到相同帧序列。
直觉
接收调用像把一条纸带随手剪成几段递来。长度头告诉解析器下一条消息需要多少格,而不是要求每段纸带恰好从消息头开始。一批输入中可以只有半个头,也可以装下好几条完整消息。
保留解析状态不是把所有历史无限攒起来。完整帧交给消费者后,解析器只需记住尚未完成的那一帧;下游来不及消费时,还要暂停接收或限制输出队列。
例子与边界
同一九字节跨三次短读
两条载荷为ASCII的CAT与OK,完整字节是 00 03 43 41 54 00 02 4F 4B。接收调用故意返回三段:
| 输入批次 | 新输入 | 处理后的状态 | 本次输出 |
|---|---|---|---|
| 1 | 00 |
Header(00) |
无 |
| 2 | 03 43 41 |
Body(3,CA) |
无 |
| 3 | 54 00 02 4F 4B |
Header(空) | CAT、OK |
第二次才补满长度头,且仍差一个载荷字节。第三次的首字节T补完CAT,剩余四字节又构成完整OK帧。若每次read返回就当一条消息,三次输出都会错误。
同一九字节一次全到,或分成九次每次1字节,答案仍应是CAT、OK。零长度帧00 00后接00 01 58应输出空载荷和X;若解析器只在Body里收到新字节才检查完成,就会漏掉空帧。
失败应在哪一步发生
FF FF给出65535,读完头就拒绝,不能先分配65535字节再检查。真实协议的最大值可能更大,但必须在分配、长度加法及类型转换前检查上限和溢出。只限制单帧长度也不能阻止无限多个合法小帧塞满消费者队列。
00后EOF是截断头;00 03 43 41后EOF是截断载荷;完整CAT帧后EOF是格式边界。非阻塞接收的EAGAIN表示当前没有数据,不是EOF,也不能清空半帧状态。错误中止时已经输出的早先完整帧仍然存在,解析器没有撤回它们的权力。
推论与应用
用输入游标避免反复搬移整个余串,每个输入字节处理常数次,解析成本为
完整帧可以继续做字段校验、请求关联与业务处理。分帧只保证边界可解析,不验证身份、不保证请求成功,也不处理响应丢失后的业务结果理路RPC结果判定与重试的不确定性RPC outcome uncertainty · Unknown outcome · Retry semantics为一个逻辑请求维护待定、成功、明确失败与结果未知状态,用不可区分轨迹解释响应丢失、重连和deadline后仍可能执行。。可复算实现与任意切分测试见网络终点任务。