C语言接收数据、解析数据帧,解决丢包粘包问题
如果在开发中碰到需要解析大量数据且存在粘包现象的情况下:
数据帧格式:0xAA(包头) + 0xXX(命令) + 0xXX(长度) + 数据部分 + 0xXX(CRC)
下列函数可以从一串数据中提取一帧数据:
-
提供帧同步能力(遇到中断帧或新帧头重新同步);
-
高效接收并丢弃非法帧(溢出清空、错误帧重起)。
#include <stdint.h>
#include <stdbool.h>
#include <string.h>#define MAX_FRAME_LENGTH 1024
#define FRAME_HEADER 0xAAuint8_t buffer[MAX_FRAME_LENGTH];
int bufferLen = 0;
bool foundStart = false;
int expectedLength = -1;void ProcessReceivedData(uint8_t* frame, int len); // 处理数据帧函数,需你实现void ProcessIncomingBytes(uint8_t* data, int length)
{for (int i = 0; i < length; i++){uint8_t b = data[i];if (!foundStart){if (b == FRAME_HEADER){bufferLen = 0;buffer[bufferLen++] = b;foundStart = true;expectedLength = -1;}continue;}buffer[bufferLen++] = b;// 解析长度字段(第 3 个字节)if (bufferLen == 3 && expectedLength == -1){uint8_t dataLen = buffer[2];expectedLength = 1 + 1 + 1 + dataLen + 1; // 帧头 + 命令 + 长度 + 数据 + CRC}// 如果再次遇到 0xAA,可能是新一帧开始if (b == FRAME_HEADER && bufferLen > 1){bufferLen--; // 移除当前 0xAAif (expectedLength > 0 && bufferLen == expectedLength){ProcessReceivedData(buffer, bufferLen);}buffer[0] = FRAME_HEADER;bufferLen = 1;expectedLength = -1;continue;}// 收到完整帧if (expectedLength > 0 && bufferLen == expectedLength){ProcessReceivedData(buffer, bufferLen);bufferLen = 0;foundStart = false;expectedLength = -1;}// 错误保护:溢出处理if (bufferLen > MAX_FRAME_LENGTH){bufferLen = 0;foundStart = false;expectedLength = -1;}}
}