你收到了两个字节。
此时应当打开信,还是等一等?
如果协议规定长度头本身就要四个字节,接收端还没有足够信息知道正文有多长。合理的行为是保留已得的字节,等待后续;不能把“暂时不完整”伪装成空消息或成功。
收到不足四字节的头,是等待;完整头宣称超过协议上限,是拒绝。头合法但正文未齐,是等待;完整正文无法按约定解析,则是拒绝。
这几个分支都要有明确的依据。接收器不应因为一次读取结束,就假设消息也结束了。
在工作台按 1、2、5 字节循环喂入同一段帧,观察何时第一次产生完整消息。缓冲区只是暂存“还不能作出完整解释”的内容。
把两帧粘在一起输入,接收器应该取出第一帧,再处理余下字节。我们给 unpack(buffer) 的约定是:
Decoder 循环调用这个函数。自己写接收侧时,先把一次调用的边界做好,再由外层循环组成持续读取。
再截掉批次末尾一个字节。如果前一帧完整,它可以已被解析;后面的半条仍须报告未完成。不能把“已经解析一条”偷换成“整批全部成功”。
V1 区分 data 和 ack。data 的正文是什么,由双方约定和人解释;ack 则必须给出 reply_to 和 stage。
received 表示对原消息收件的声明;accepted 表示接受原内容的声明。二者都不自动等于真实动作已完成。本首版没有提供一个会凭空证明真实执行的 completed 回执。
检查来信中声明的固定端点、编号和阶段,再决定怎样回复。一份无法关联自己发件的回执,会留作实际收到的消息,但不成为“原消息已确认”的证据。
点击“确认收到这封消息”,并不会在另一端直接点亮状态。它先构造一封 ack,再经过相同的模拟通道。回执可以丢,回执的回执也可以丢。
回到引子,这正是递归确认难以结束的地方。我们现在至少可以指出:这一份证据在哪里产生,通过哪条消息送达,支持的是哪一层确认。
V1 编号让关联变得明确,但它没有自动提供去重。本机手工重投相同帧,对方仍可能看到两份。可靠性支线以后会讨论如何保留处理结果、怎样在重复来信时回应。
在 practice/student.py 补上 unpack(buffer),先用参考发送器造出的字节检验它:每个截断位置、两帧粘连、错误长度和无效 UTF-8 都要有符合约定的结果。
把自己的“等待、解析、拒绝”条件解释给发送端搭档,并选择一条实际来信发回关联回执。最后到 汇合验收,让两端真正互通。