用单一流式组帧器可靠解析连续字节流
串口、TCP、USB 收到的都是连续字节。一次读取有时只有半帧,有时又会挤进两帧。
第一次收到:帧头 + 长度 + 半段内容
第二次收到:剩余内容 + 校验 + 下一帧所以,一次读取不等于一条消息。
只用一个组帧器
把收到的每个字节,按顺序交给同一个状态机。状态机记住自己正在等待什么:
- 等帧头。
- 等长度。
- 按长度收集内容。
- 检查校验,交出完整帧。
业务代码只接收完整帧,不直接翻动接收缓存。这样就不会出现两个解析器争抢同一批数据的问题。
半包保留,粘包继续解析
数据没收完时,保留当前状态,等下次收到字节后接着解析。这就是处理半包。
一帧完成后,立即交给业务代码。若缓存里还有字节,就继续寻找下一帧。这就是拆开粘包。
不要等待串口安静,也不要把一次读取当成帧尾。连续发送时可能一直没有空闲间隔。
出错后重新找帧头
解析器会逐字节匹配。某个字节匹配失败时,状态机退回寻找帧头,只丢弃这个失败字节。它后面的字节仍留在输入流中,继续逐个解析,不能清空整个接收缓存。
长度超限、校验失败或等待太久时,也要放弃当前残帧,重新寻找帧头。后续尚未解析的字节继续保留。
这类解析器只需长期保存少量状态:当前阶段、已收长度、目标长度、校验值和帧缓存。
TinyFrame 的核心做法也是逐字节推进状态,完整且校验通过后才交付消息。
最后记住一句话:字节来了就喂给状态机,半包留下,整帧交付,剩余字节继续解析。