简体   繁体   English

在C ++中解析缓冲区数据

[英]Parsing buffer data in C++

My C++ project has a buffer which could be any size and is filled by Bluetooth. 我的C ++项目有一个可以是任何大小的缓冲区,并由Bluetooth填充。 The format of the incoming messages is like 0x43 0x0B 0x00 0x06 0xA2 0x03 0x03 0x00 0x01 0x01 0x0A 0x0B 0x0B 0xE6 0x0D in which starts with 0x43 and ends with 0x0D. 传入消息的格式类似于0x43 0x0B 0x00 0x06 0xA2 0x03 0x03 0x00 0x01 0x01 0x0A 0x0B 0x0B 0xE6 0x0D,其中以0x43开头并以0x0D结尾。 So, it means that each time when buffer is filled, it can have different order of contents according to the above message format. 因此,这意味着每次填充缓冲区时,根据上述消息格式,缓冲区的内容顺序可以不同。

static const int BufferSize = 1024;
byte buffer[BufferSize];
  1. What is the best way to parse the incoming messages in this buffer? 在此缓冲区中解析传入消息的最佳方法是什么?
  2. Since I have come from Java and .NET, What is the best way to make each extracted message as an object? 既然我来自Java和.NET,将每个提取的消息作为对象的最佳方法是什么? Class could be solution? 上课可以解决吗?
  3. I have created a separate class for parsing the buffer like bellow, am I in a right direction? 我创建了一个单独的类来像下面这样解析缓冲区,我的方向正确吗?

#include<parsingClass.h>
class A
{
   parsingClass ps;
public:
   parsingClass.parse(buffer, BufferSize);
}
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);
   }
};

Can you have the parser as a method of a 'ProtocolUnit' class? 您可以将解析器作为“ ProtocolUnit”类的方法吗? The method could take a buffer pointer/length as a parameter and return an int that indicates how many bytes it consumed from the buffer before it correctly assembled a complete protocol unit, or -1 if it needs more bytes from the next buffer. 该方法可以将缓冲区指针/长度作为参数,并返回一个int值,该值指示在正确组装完整的协议单元之前从缓冲区消耗了多少字节;如果需要从下一个缓冲区获取更多字节,则返回-1。

Once you have a complete ProtocolUnit, you can do what you wish with it, (eg. queue it off to some processing thread), and create a new one for the remaining bytes/next buffer. 一旦有了完整的ProtocolUnit,就可以使用它进行所需的操作(例如,将其排队到某个处理线程中),并为剩余的字节/下一个缓冲区创建一个新的。

My C++ project has a buffer which could be any size 我的C ++项目有一个可以是任意大小的缓冲区

The first thing I notice is that you have hard-coded the buffer size. 我注意到的第一件事是您已经硬编码了缓冲区大小。 You are in danger of buffer overflow if an attempt is made to read data bigger than the size you have specified into the buffer. 如果尝试读取大于您在缓冲区中指定的大小的数据,则有缓冲区溢出的危险。

If possible keep the buffer size dynamic and create the byte array according to the size of the data to be received into the buffer. 如果可能,保持动态缓冲区大小,并根据要接收到缓冲区的数据大小创建字节数组。 Try and inform the object where your byte array lives of the incoming buffer size, before you create the byte array. 在创建字节数组之前,请尝试将传入缓冲区大小告知对象字节数组所在的位置。

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

What is the best way to parse the incoming messages in this buffer? 在此缓冲区中解析传入消息的最佳方法是什么?

You are on the right lines, in that you have created and are using a parser class. 您处于正确的位置,因为您已经创建并正在使用解析器类。 I would suggest using memcpy to copy the individual data items one at a time, from the buffer to a variable of your choice. 我建议使用memcpy一次将单个数据项复制一次,从缓冲区复制到您选择的变量。 Not knowing the wider context of your intention at this point, I cannot add much to that. 在这一点上,我不知道你意图的更广泛的背景,我对此无能为力。

Since I have come from Java and .NET, What is the best way to make each extracted message as an object? 既然我来自Java和.NET,将每个提取的消息作为对象的最佳方法是什么? Class could be solution? 上课可以解决吗?

Depending on the complexity of the data you are reading from the buffer and what your plans are, you could use a class or a struct. 根据您从缓冲区读取的数据的复杂性以及您的计划,可以使用类或结构。 If you do not need to create an object with this data, which provides services to other objects, you could use a struct. 如果不需要使用此数据创建为其他对象提供服务的对象,则可以使用结构。 Structs are great when your need isn't so complex, whereby a full class might be overkill. 当您的需求不是那么复杂时,结构很好,因此一堂完整的课可能会显得过大。

I have created a separate class for parsing the buffer like bellow, am I in a right direction? 我创建了一个单独的类来像下面这样解析缓冲区,我的方向正确吗?

I think so. 我认同。

I hope that helps for starters! 希望对初学者有所帮助!

The question "how should I parse this" depends largely on how you want to parse the data. 这个问题:“我应该如何解析这个”你想如何分析数据在很大程度上依赖。 Two things are missing from your question: 您的问题缺少两件事:

  1. Exactly how do you receive the data? 您究竟如何接收数据? You mention Bluetooth but what is the programming medium? 您提到了蓝牙,但是编程媒介是什么? Are you reading from a socket? 您正在从套接字读取吗? Do you have some other kind of API? 您还有其他类型的API吗? Do you receive it byte at a time or in blocks? 您是一次接收还是按字节接收?
  2. What are the rules for dealing with the data you are receiving? 处理收到的数据有哪些规则? Most data is delimited in some way or of fixed field length. 大多数数据以某种方式定界或具有固定的字段长度。 In your case, you mention that it can be of any length but unless you explain how you want to parse it, I can't help. 在你的情况,你提到它可以是任何长度,但除非你能解释一下你想怎么解析它,我也没有办法。

One suggestion I would make is to change the type of your buffer to use std::vector : 我的一个建议是将缓冲区的类型更改为使用std::vector

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

You should choose normalSize to be something around the most frequently observed size of your incoming message. 您应该选择normalSize使其与收到的消息中最经常观察到的大小保持一致。 A vector will grow as you push items onto it so, unlike the array you created, you won't need to worry about buffer overrun if you get a large message. 向量会随着您将项目推入其中而增长,因此,与您创建的数组不同,如果收到大消息,则无需担心缓冲区溢出。 However, if you do go above normalSize under the covers the vector will reallocate enough memory to cope with your extended requirements. 但是,如果您确实超出了标准的标准normalSize ,向量将重新分配足够的内存来满足您的扩展需求。 This can be expensive so you don't want to do it too often. 这可能很昂贵,所以您不想经常这样做。

You use a vector in pretty much the same way as your array. 使用向量的方式几乎与数组相同。 One key difference is that you can simply push elements onto the end of the vector, rather than having to keep a running pointer. 一个主要的区别是您可以将元素简单地推到向量的末尾,而不必保留正在运行的指针。 SO imagine you received a single int at a time from the Bluetooth source, your code might look something like this: 想象一下您一次从蓝牙源接收到一个整数,您的代码可能看起来像这样:

// 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.

The key benefit is that array will automatically resize the vector without you having to do it no matter whether the amount of characters pushed on is 10 or 10,000. 关键好处是,无论输入的字符数是10还是10,000,数组都将自动调整向量的大小,而您不必这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM