Вычитать сообщения из потока байт

212
15 июля 2022, 23:10

Иметься поток байт, т.е. постоянно идут сообщения в байтах. Сообщения имеют разную длину. Все сообщения начинаются символом # (или в hex 0x23). Символ # может быть только в начале сообщения! Как вычитывать сообщения в массив char от символа # до след символа #, при разной длине сообщений при этом не терять сообщения? Поскольку они идут непрерывно с какой-то частотой.

К примеру поток байт:

0x23, 0х24, 0x50, 0x57, 0x52, 0x2C, 0x01, 0х23, 0х34, 0x35, 0x23, 0x25, 0x25, 0x27, 0x28, 0x29, 0x30, 0x31, 0x24, 0x44, 0x45, 0x46, 0x23, ...

В случае если одно сообщение байт:

uint8_t mess[] = {0х23, 0х34, 0x35, 0x36, 0x44};
char buffer[sizeof(mess) + 1];
memcpy(buffer, mess, sizeof(mess));
buffer[sizeof(mess)] = '\0';
if ((buffer[0] == '#' || buffer[0] == 0x23)
{
 // какие-то действия
}
Answer 1

Набросал код

#include <iostream>
#include <cassert>
class Reader
{
    std::string tail;
    public:
        void read(const std::string& s)
        {
            tail = tail+s;
            if (tail.empty()) return;
            assert(tail[0] == '#');
            while (true) {
                size_t f = tail.find('#',1);
                if (f == std::string::npos) return;
                std::string message = tail.substr(0, f);
                // отпроцессим сообщение - выведем в консоль
                std::cout << message << '\n';
                // можно было выше не копировать, а просто прислать кусок
                // удалим с хвоста
                tail.erase(0, f);
            }
        }
        std::string get_tail() const { return tail;}
};
int main(){
    Reader r;
    r.read("#123#11#");
    r.read("1111111");
    r.read("#9999#");
    r.read("###");
    std::cout << r.get_tail();
}

последнее сообщение всегда остается в буфере, так как мы не знаем, оно уже закончилось или нет. функция read получает данные произвольными кусками. В самом конце, когда соединение будет закрыто, можно взять последнее сообщение через get_tail. Остальные функции дописывайте по надобности.

Если у Вас в одном пакете приходят сразу много сообщений, то может есть смысл переделать внутренности цикла, что бы не делать сколько копирований.

READ ALSO
Теорема о разделяющей оси на C++

Теорема о разделяющей оси на C++

Я пытаюсь реализовать обработку столкновений с помощью SAT, но в интернете встречается лишь теория о отрывки практикиУ меня появилось два...

349
Ошибка разыменования указателя в С++

Ошибка разыменования указателя в С++

ЗдравствуйтеПочему когда я разыменовываю pointer вылетает ошибка?

286
что возвращает decltype и как он работает?

что возвращает decltype и как он работает?

Всем здравствуйтеЯ начал недавно изучать c++ и столкнулся с оператором decltype

338
Создание М-мерного дерева на языке Си

Создание М-мерного дерева на языке Си

Здравствуйтe, Хочу написать собственное дерево на языке си, каждый узел которого имеет более двух потомковЯ создал структуру, в которую входит...

258