C++入门 串行通信防粘包处理

一、 串行通信使用固定数据包格式防止粘包

#include <stdio.h>
#include <string.h>

#define BUFFER_LENGTH 128
#define GB_OK 1
#define GB_NG 0

unsigned char buffer[BUFFER_LENGTH];
int bufferHead;
int bufferTail;


int NextIndex(int index,int length,int offset)
{
    index += offset;
    if(index >= length)
    {
        index -= length;
    }
    return index;
}


/*
 * 从缓冲区中读出一个有效数据包
 * 成功读取返回GB_OK
 * 未读取成功返回GB_NG
 */
int GetPacket(unsigned char *packet,int *pPacketLength)
{
    int index = bufferHead;
    int nextIndex = NextIndex(index,BUFFER_LENGTH,1);
    while(index != bufferTail && nextIndex != bufferTail)
    {
        //找到数据包头
        if (buffer[index] == 0xfa && buffer[nextIndex] == 0xfb)
        {
            //计算FA FB开始缓冲区数据长度,确定是否可以读取到长度值
            int bufferLength = bufferTail - index;
            if(bufferLength < 0) {bufferLength += BUFFER_LENGTH;}
            //判断长度是否允许读取到长度值
            if(bufferLength < 6){ return GB_NG;}

            //读取数据区长度
            int dataLength= buffer[NextIndex(index,BUFFER_LENGTH,6)] | (buffer[NextIndex(index,BUFFER_LENGTH,7)] <<8);

            //检测缓冲区长度
            //检测0xfc 0xfd
            if(bufferLength >= 12 + dataLength
                    && buffer[NextIndex(index,BUFFER_LENGTH,10 + dataLength)] == 0xfc
                    && buffer[NextIndex(index,BUFFER_LENGTH,11 + dataLength)] == 0xfd)
            {
                //找到一个packet,拷贝数据
                *pPacketLength = dataLength+12;
                for(int i=0;i<*pPacketLength;i++)
                {
                    packet[i] = buffer[NextIndex(index,BUFFER_LENGTH,i)];
                }
                //修改bufferHead
                bufferHead = NextIndex(index,BUFFER_LENGTH,*pPacketLength);
                return GB_OK;
            }
        }

        index = nextIndex;
        nextIndex = NextIndex(index,BUFFER_LENGTH,1);
    }

    return GB_NG;
}

void PrintPacket(unsigned char *packet,int packetLength)
{
    for(int i=0;i<packetLength;i++)
    {
        printf("0x%x ",packet[i]);
    }
    printf("\n");
}


/*
 * 数据包以FA FB开头
 * 数据包以FC FD结尾
 * 数据包的第7和第8位为数据包内容区域长度
 * 数据包FC FD前面的两个字节是数据包的CRC,可以是整个数据包的CRC
 * 数据包格式定义
 * FA FB XX XX XX XX LEN LEN .....CRC CRC FC FD
 */
int main() {
    //返回值
    unsigned char packet[128];
    int packetLength;

    //测试1
    printf("========================================================================================================\n");
    printf("测试1\n");
    unsigned char buffer1[] = {0xfa,0xfb,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0xcc,0xdd,0xfc,0xfd};
    memcpy(buffer,buffer1,sizeof(buffer1)/sizeof(buffer1[0]));
    bufferHead = 0;
    bufferTail = sizeof(buffer1)/sizeof(buffer1[0]);

    int getFlag = GetPacket(packet,&packetLength);
    if(getFlag == GB_OK)
    {
        printf("获取数据包成功\n");
        PrintPacket(packet,packetLength);
    }else
    {
        printf("获取数据包失败\n");
    }
    printf("bufferHead:%d\n",bufferHead);
    printf("bufferHead:%d\n",bufferTail);

    //测试2
    printf("========================================================================================================\n");
    printf("测试2\n");
    unsigned char buffer2[] = {0xfa,0xfb,0xfa,0xfb,0x00,0x00,0xff,0x00,0x01,0x00,0x00,0xcc,0xdd,0xfc,0xfd};
    memcpy(buffer,buffer2,sizeof(buffer2)/sizeof(buffer2[0]));
    bufferHead = 0;
    bufferTail = sizeof(buffer2)/sizeof(buffer2[0]);

    getFlag = GetPacket(packet,&packetLength);
    if(getFlag == GB_OK)
    {
        printf("获取数据包成功\n");
        PrintPacket(packet,packetLength);
    }else
    {
        printf("获取数据包失败\n");
    }
    printf("bufferHead:%d\n",bufferHead);
    printf("bufferHead:%d\n",bufferTail);

    return 0;
}
  printFloatInfo(-9.25);
    return 0;
}
/*
输出结果
========================================================================================================
测试1
获取数据包成功
0xfa 0xfb 0x0 0x0 0x1 0x0 0x1 0x0 0x0 0xcc 0xdd 0xfc 0xfd 
bufferHead:13
bufferHead:13
========================================================================================================
测试2
获取数据包成功
0xfa 0xfb 0x0 0x0 0xff 0x0 0x1 0x0 0x0 0xcc 0xdd 0xfc 0xfd 
bufferHead:15
bufferHead:15

*/

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值