【问题标题】:stream data into a byte array将数据流式传输到字节数组中
【发布时间】:2017-06-28 12:21:05
【问题描述】:

我不得不承认我现在有点困惑,如果问题不是很清楚或微不足道,我很抱歉(实际上我希望是后者)......

我正在通过网络发送一个字节数组,并希望在发送方做这样的事情:

size_t max_size = 100;
uint8_t buffer[size];
idontknowwhat_t x{buffer};    
uint16_t size = 11;                 // total number of bytes in the buffer
uint16_t id_a,id_b,id_c;            // some ids
uint8_t  a,b,c;                     // some data
x << size << id_a << a << id_b << b << id_c << c;
someMethodToSend(buffer,size);

在接收端是这样的:

size_t max_size = 100;
uint8_t buffer[size];
someMethodToReceive(buffer);
idontknowwhat_t x{buffer};
uint16_t size;
x >> size;
for (uint16_t i=0; i<size-2; i++) {
    uint16_t id;
    uint8_t data;
    x >> id >> data;
    std::cout << id << " " << data;
}

所以我的目标基本上是避免丑陋的强制转换和手动递增指针,同时能够在缓冲区中有uint8_tuint16_t(也可能还有uint32_t)。我在这里放入缓冲区的数据只是一个示例,我知道在通过网络发送时我需要注意字节顺序(如果我必须“手动”执行此操作会很好)。

有什么东西可以用来代替我假设的idontknowwhat_t 吗?

【问题讨论】:

  • 我认为boost::asio::streambuf 应该没问题,但我不确定它使用的内部缓冲区是否适合您的用例。
  • @Rakete1111 我想我已经看过了,但是在阅读了太多关于流的不同地方之后,我有点困惑。我会试一试,谢谢提示

标签: c++ stream bytebuffer


【解决方案1】:

你不能真正避免做丑陋的演员表,但至少你可以将它们隐藏在 idontknowwhat_t 类的 operator&gt;&gt;operator&lt;&lt; 函数中。使用模板,您可以将代码中的强制转换次数限制在最低限度。

class idontknowwhat_t
{
    uint8_t* _data;

public:
    idontknowwhat_t(uint8_t* buffer)
        : _data(buffer)
    {}

    template<typename insert_type>
    idontknowwhat_t& operator<<(insert_type value)
    {
        *reinterpret_cast<insert_type*>(_data) = value;
        _data += sizeof(insert_type);
        return *this;
    }
    template<typename extract_type>
    idontknowwhat_t& operator>>(extract_type& value)
    {
        value = *reinterpret_cast<extract_type*>(_data);
        _data += sizeof(extract_type);
        return *this;
    }
};

我认为这实际上可以直接与您的代码一起使用。在这个例子中,idontknowwhat_t 类不拥有缓冲区,只是保留了一个原始指针,指向它期望读取或写入的下一位数据。出于实际目的,我建议让idontknowwhat_t 类管理缓冲内存。

此外,此页面上的任何代码实际上都没有处理数据的字节顺序,这肯定是idontknowwhat_t 类的责任。为此有一个boost library。我没有在这里记录该库的使用,因为我认为它会分散问题的真正意义。

【讨论】:

  • 这看起来不错。我很确定有我需要的所有提升课程,但我没有设法采用我发现的example 来满足我的需要。只要接收者事先知道要接收什么就很容易,但是如果消息中的类型被编码在消息本身中,我就很迷茫了。顺便说一句,我认为这种演员阵容并不丑陋,因为它仅限于几行而且调用者不会注意到它的存在
  • Re“只要接收者事先知道要接收什么就很容易,但是如果消息中的类型被编码在消息本身中,我就很迷茫了”。这与字节顺序不同。接收者必须知道它期待什么——至少,它必须告诉idontknowwhat_t 它希望返回值具有什么数据类型。您能否更具体地说明您要实现的目标?
  • 确保评论与字节顺序无关。我的意思是消息不是固定的结构,而只是遵循固定的协议,例如。 (保留问题中的示例)id 的某个值可能表示下一个值是uint32_t,而另一个值可能表示下一个值是uint16_t
  • ...实际上在实际代码中,前两个字节是uint16_t,表示接下来会发生什么。
  • 这听起来像是你的第二段代码的责任。您可以将第一个 id 标志读取为 uint16_t,并将其放入 switch 语句中。这个 switch 语句的不同情况可以以他们喜欢的任何方式读取缓冲区。
【解决方案2】:

你试过std::list吗?您可以将元素分组为类型并将它们放入具有适当类型的列表中。然后你可以创建一个 std::list 的 std::list。

【讨论】:

  • 不,我不想通过网络发送列表。我想发送一个字节数组,所以我不明白 std::list 会有什么帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多