Я получаю сообщения из сокета. Сокет упакован в заголовок (это в основном размер сообщения) и нижний колонтитул, который является cr c (своего рода код, чтобы проверить, не повреждено ли сообщение)
Итак, макет выглядит примерно так:
size (2 bytes) | message (240 bytes) | crc (4 byte)
Я написал operator>>
operator>>
выглядит следующим образом:
std::istream &operator>>(std::istream &stream, Message &msg) {
std::int16_t size;
stream >> size;
stream.read(reinterpret_cast<char*>(&msg), size);
// Not receive enough data
if (stream.rdbuf()->in_avail() < dataSize + 4) {
stream.setstate(std::ios_base::failbit);
return stream;
}
std::int16_t gotCrc;
stream >> gotCrc;
// Data not received correctly
if(gotCrc != computeCrc(msg)) {
stream.setstate(std::ios_base::failbit);
}
return stream;
}
Сообщение может поступать побайтово или может прибыть полностью. Мы можем даже получить несколько сообщений за один раз.
По сути, я сделал что-то вроде этого:
struct MessageReceiver {
std::string totalDataReceived;
void messageArrived(std::string data) {
// We add the data to totaldataReceived
totalDataReceived += data;
std::stringbuf buf(totalDataReceived);
std::istream stream(&buf);
std::vector<Message> messages(
std::istream_iterator<Message>(stream),
std::istream_iterator<Message>{});
std::for_each(begin(messages), end(messages), processMessage);
// +4 for crc and + 2 for the size to remove
auto sizeToRemove = [](auto init, auto message) {return init + message.size + 4 + 2;};
// remove the proceed messages
totalDataReceived.remove(accumulate(begin(messages), end(messages), 0, sizeToRemove);
}
};
Итак, в основном, мы получаем данные, мы вставляем их в общий массив данных получил. Мы транслируем его, и если мы получили хотя бы одно сообщение, мы удаляем его из буфера totalDataReceived
.
Однако я не уверен, что это хороший способ для go. На самом деле, этот код не работает, когда вычисление неверно cr c ... (сообщение не создано, поэтому мы не повторяем его). Поэтому каждый раз я буду пытаться прочитать сообщение с ошибкой cr c ...
Как я могу это сделать? Я не могу сохранить все данные в totalDataReceived
, потому что я могу получать много сообщений в течение времени выполнения.
Должен ли я реализовать свой собственный streambuf?