2

我的 C++ 项目有一个缓冲区,它可以是任意大小并由蓝牙填充。传入消息的格式类似于 0x43 0x0B 0x00 0x06 0xA2 0x03 0x03 0x00 0x01 0x01 0x0A 0x0B 0x0B 0xE6 0x0D 其中以 0x43 开头并以 0x0D 结尾。因此,这意味着每次缓冲区被填满时,根据上述消息格式,它可以有不同的内容顺序。

static const int BufferSize = 1024;
byte buffer[BufferSize];
  1. 解析此缓冲区中传入消息的最佳方法是什么?
  2. 由于我来自 Java 和 .NET,将每个提取的消息作为对象的最佳方法是什么?类可能是解决方案?
  3. 我已经创建了一个单独的类来解析缓冲区,如下所示,我的方向是否正确?

#include<parsingClass.h>
class A
{
   parsingClass ps;
public:
   parsingClass.parse(buffer, BufferSize);
}
4

4 回答 4

2

您可以将解析器作为“ProtocolUnit”类的方法吗?该方法可以将缓冲区指针/长度作为参数,并返回一个 int 值,指示它在正确组装完整协议单元之前从缓冲区消耗了多少字节,或者如果它需要来自下一个缓冲区的更多字节,则返回 -1。

一旦你有了一个完整的 ProtocolUnit,你可以用它做你想做的事,(例如,将它排到某个处理线程),并为剩余的字节/下一个缓冲区创建一个新的。

于 2012-10-18T12:57:52.347 回答
2
class ReturnMessage{
    char *message; 
    public:
    char *getMessage(unsigned char *buffer,int count){
         message = new char[count];
         for(int i = 1; i < count-2; i++){
            message[i-1] = buffer[i];
         }
         message[count-2] = '\0';
         return message;
    }
};
class ParserToMessage{
static int BufferSize = 1024;
unsigned char buffer[BufferSize];
unsigned int counter;
public:
  static char *parse_buffer()
  {
     ReturnMessage rm;
     unsigned char buffByte;
     buffByte = blueToothGetByte(); //fictional getchar() kind of function for bluetooth
     if(buffByte == 0x43){
        buffer[counter++] = buffByte;
        //continue until you find 0x0D
        while((buffByte = blueToothGetByte()) != 0x0D){
            buffer[counter++] = buffByte;
        }
     }
     return rm.getMessage(buffer,counter);
   }
};
于 2012-10-18T12:29:29.433 回答
1

“我应该如何解析这个”的问题很大程度上取决于您想要如何解析数据您的问题缺少两件事:

  1. 您究竟是如何接收数据的?你提到蓝牙,但什么是编程媒介?你是从套接字读取的吗?你有其他类型的API吗?您是一次接收一个字节还是分块接收它?
  2. 处理您收到的数据的规则是什么?大多数数据以某种方式或固定字段长度分隔。在您的情况下,您提到它可以是任意长度,但除非您解释要如何解析它,否则我无能为力。

我会提出的一个建议是更改要使用的缓冲区类型std::vector

std::vector<unsigned char> buffer(normalSize)

您应该选择normalSize在收到消息的最常观察到的大小附近。向量会随着您将项目推送到其上而增长,因此,与您创建的数组不同,如果您收到一条大消息,您无需担心缓冲区溢出。但是,如果您确实超出normalSize了封面,则向量将重新分配足够的内存来应对您的扩展需求。这可能很昂贵,因此您不想经常这样做。

您使用向量的方式与数组的使用方式几乎相同。一个关键的区别是您可以简单地将元素推到向量的末尾,而不必保留一个正在运行的指针。所以想象你一次从蓝牙源收到一个 int,你的代码可能看起来像这样:

// Clear out the previous contents of the buffer.
buffer.clear();

int elem(0);
// Find the start of your message. Throw away elements
// that we don't need.
while ( 0x43 != ( elem = getNextBluetoothInt() ) );

// Push elements of the message into the buffer until
// we hit the end.
while ( 0x0D != elem )
{
    buffer.push_back( elem );
}
buffer.push_back( elem ); // Remember to add on the last one.

关键的好处是,无论推送的字符数是 10 还是 10,000,数组都会自动调整向量的大小,而无需您这样做。

于 2012-10-18T13:15:43.283 回答
1

我的 C++ 项目有一个可以是任意大小的缓冲区

我注意到的第一件事是您对缓冲区大小进行了硬编码。如果尝试将大于您指定大小的数据读取到缓冲区中,您将面临缓冲区溢出的危险。

如果可能,请保持缓冲区大小动态,并根据要接收到缓冲区中的数据大小创建字节数组。在创建字节数组之前,尝试通知对象传入缓冲区大小的字节数组所在的位置。

int nBufferSize = GetBufferSize();
UCHAR* szByteArray = new UCHAR[nBufferSize];

解析此缓冲区中传入消息的最佳方法是什么?

您在正确的路线上,因为您已经创建并正在使用解析器类。我建议使用memcpy一次将单个数据项从缓冲区复制到您选择的变量。在这一点上不知道你意图的更广泛背景,我不能补充太多。

由于我来自 Java 和 .NET,将每个提取的消息作为对象的最佳方法是什么?类可能是解决方案?

根据您从缓冲区读取的数据的复杂性以及您的计划,您可以使用类或结构。如果您不需要使用此数据创建为其他对象提供服务的对象,则可以使用结构。当您的需求不那么复杂时,结构体非常棒,因此一个完整的类可能是矫枉过正的。

我已经创建了一个单独的类来解析缓冲区,如下所示,我的方向是否正确?

我认同。

我希望这对初学者有帮助!

于 2012-10-18T12:53:22.210 回答