使用流处理接收到的数据

Using stream to treat received data

本文关键字:数据 处理      更新时间:2023-10-16

我正在接收来自套接字的消息。套接字被封装在一个报头(基本上是消息的大小(和一个页脚(crc(一种检查消息是否损坏的代码(中

因此,布局类似于:

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中删除。

然而,我不确定这是一条好路。事实上,当一个计算错误的crc。。。(消息未创建,因此我们不会对其进行迭代(。所以每次,我都会尝试读取带有错误crc的消息。。。

我该怎么做?我不能把所有的数据都保存在totalDataReceived中,因为在执行生命周期中我可以接收到很多消息。

我应该实现自己的streambuf吗?

我发现您想要创建的是一个类似std::istream的类。当然,您可以选择创建自己的类,但出于某些原因,我更喜欢实现std::streambuf。

首先,使用您的类的人习惯于使用它,因为如果您继承并实现std::streambuf和std::istream,它的作用与std::distream相同。

其次,您不需要创建额外的方法,也不需要重写运算符。它们已经在std::istream的类级别中准备好了。

要实现std::streambuf,您必须继承它,重写underflow((并使用setg((设置get指针。