C语言接收数据、解析数据帧,解决丢包粘包问题

发布于:2025-05-22 ⋅ 阅读:(19) ⋅ 点赞:(0)

        如果在开发中碰到需要解析大量数据存在粘包现象的情况下:

        数据帧格式:0xAA(包头) + 0xXX(命令) + 0xXX(长度) + 数据部分 + 0xXX(CRC)

        下列函数可以从一串数据中提取一帧数据:

  • 提供帧同步能力(遇到中断帧或新帧头重新同步);

  • 高效接收并丢弃非法帧(溢出清空错误帧重起)。

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#define MAX_FRAME_LENGTH 1024
#define FRAME_HEADER 0xAA

uint8_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--;  // 移除当前 0xAA
            if (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;
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到