用单一流式组帧器可靠解析连续字节流

串口、TCP、USB 收到的都是连续字节。一次读取有时只有半帧,有时又会挤进两帧。

第一次收到:帧头 + 长度 + 半段内容
第二次收到:剩余内容 + 校验 + 下一帧

所以,一次读取不等于一条消息

只用一个组帧器

把收到的每个字节,按顺序交给同一个状态机。状态机记住自己正在等待什么:

  1. 等帧头。
  2. 等长度。
  3. 按长度收集内容。
  4. 检查校验,交出完整帧。

业务代码只接收完整帧,不直接翻动接收缓存。这样就不会出现两个解析器争抢同一批数据的问题。

半包保留,粘包继续解析

数据没收完时,保留当前状态,等下次收到字节后接着解析。这就是处理半包。

一帧完成后,立即交给业务代码。若缓存里还有字节,就继续寻找下一帧。这就是拆开粘包。

不要等待串口安静,也不要把一次读取当成帧尾。连续发送时可能一直没有空闲间隔。

出错后重新找帧头

解析器会逐字节匹配。某个字节匹配失败时,状态机退回寻找帧头,只丢弃这个失败字节。它后面的字节仍留在输入流中,继续逐个解析,不能清空整个接收缓存。

长度超限、校验失败或等待太久时,也要放弃当前残帧,重新寻找帧头。后续尚未解析的字节继续保留。

这类解析器只需长期保存少量状态:当前阶段、已收长度、目标长度、校验值和帧缓存。

TinyFrame 的核心做法也是逐字节推进状态,完整且校验通过后才交付消息。

最后记住一句话:字节来了就喂给状态机,半包留下,整帧交付,剩余字节继续解析。