【问题标题】:alternatives to std::string to use with boost::asio与 boost::asio 一起使用的 std::string 的替代品
【发布时间】:2011-03-09 15:49:24
【问题描述】:

boost::asio 的各种readwrite 函数和方法接受boost::asio::buffer。根据buffer's documentation,可变的std::string 不能包装在boost::asio::buffer 中,因此不能用于asio 的read 函数。这可能是因为std::string 不允许对其内部缓冲区进行可变访问(这在之前here 中讨论过)。

这很遗憾,因为std::string 是一种在 C++ 中表示可变数据缓冲区的便捷方式。没有它,我们要么只剩下 POD 阵列,boost::arraystd::vector<char>。前两个对于可变长度消息不方便。 std::vector<char> 可以工作,但在 (*) 周围携带数据缓冲区是一种不自然的方式

问题:

  1. 对于读取缓冲区,std::stringboost::asio 是否有其他替代方案?我在这里遗漏了什么吗?
  2. 我想知道为什么std::vector<char> 在可变缓冲区中被支持。是因为它保证其内部缓冲区在内存中是连续的,并允许使用&vec[0] 对其进行可变访问吗?

提前致谢


(*) 恕我直言。以protobuf 序列化为例 - 它提供序列化为std::string,但不提供序列化为std::vector<char>,至少不明确。


编辑:我最终还是使用了vector<char>protobuf 允许通过带有指针的SerializeToArray 调用序列化为vector<char>&vec[0] 可以在那里传递)。

【问题讨论】:

  • 我通常使用vector<char> - 因为我发现在所有情况下处理接收到的数据的操作都更快。但是我也看到了asio::streambuf 的用法:boost.org/doc/libs/1_40_0/doc/html/boost_asio/reference/…
  • @Nim:我考虑过asio::streambuf,但它对于固定大小的读取似乎有问题,并且更适合read_until 就像在HTTP 中一样。但我可能会遗漏一些东西......
  • @Eli:我一直发现std::vector<unsigned char> 是表达字节缓冲区的自然方式。 char 的未知签名很烦人......从语义上讲,string 并没有真正的意义。不要忘记protobuf 建议序列化为纯文本,在这种情况下string 确实看起来很自然。
  • @Mattieu M.:我不认为protobuf 建议序列化为纯文本,它的序列化输出肯定看起来像二进制数据(不是ascii)
  • @Eli 我不确定您所说的asio::streambuf 对固定大小的读取有问题是什么意思。我已经在几个项目中成功使用它,它与 Boost.Serialization 很好地集成在一起。您能否编辑您的问题以澄清您的疑虑?

标签: c++ boost-asio


【解决方案1】:

使用&str[0] 对字符串缓冲区的可变访问在所有已知实现上都可以正常工作,并且即将到来的 C++0x 标准化的措辞使其正式被允许。

不过,我认为 std::vector 是可变长度缓冲区的不自然表示,我认为你是疯了。

【讨论】:

  • Ben,这听起来不错,但是asio::buffer 没有构造函数采用非常量std::string,那么如何将它传递给asio?难道asio 目前不想依赖非严格标准的行为?
  • std::string转换为asio::bufferasio::buffer(&str[0], str.size())
  • 我明白了,但这不是当前的标准 C++?它受约定支持,应该是 C++0X 的一部分?
  • 目前取决于实现,字符串数据是否存在于连续数组中。在将其添加到 C++0x 标准草案之前,委员会调查了他们能找到的所有库实现,没有一个做任何不连续的事情。
  • @Alan:不能保证对c_str() 缓冲区所做的更改会合并到字符串中,或​​者缓冲区甚至是可写的。
【解决方案2】:

这是为了回答Eli的评论

我没有在我的 最初的问题,确实是因为它 我不是 100% 清楚如何使用它 具有固定大小的读取和 asio。可以 你指向一个例子(或添加一个作为 一个答案)显示如何阅读 固定长度的块成 std::sstream?

这里是 a previous answer 关于使用 asio::streambufBoost.Serialization。 asiodocumentation也有同步读取的例子:

boost::asio::streambuf b;

// reserve 512 bytes in output sequence
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512);

size_t n = sock.receive(bufs);

// received data is "committed" from output sequence to input sequence
b.commit(n);

std::istream is(&b);
std::string s;
is >> s;

【讨论】:

    【解决方案3】:

    1) 可以通过检查asio::buffer() 函数找到替代方案,重载返回mutable_buffers_1。更灵活(但可能不是最佳)的选项是asio::streambuf,对(async_)read_until 很有用。

    如果你有固定大小的字段协议,你可以使用asio::mutable_buffer 的数组。例如

    using boost::asio;
    int i;
    short s;
    char data[data_size]; // data_size is defined elsewhere
    boost::array<asio::mutable_buffer, 3> bufs = {
        asio::buffer(&i, 4), 
        asio::buffer(&s, 2),
        asio::buffer(data, data_size)
    };
    asio::read(socket, buffer(bufs)); // socket defined elsewhere
    

    2) 你已经引用了这个问题的好答案:"How to asynchronously read to std::string using Boost::asio?"

    【讨论】:

    • 是的,确实,我的问题中已经提到了您在此处列出的所有内容(包括固定数组方法)。无论如何,谢谢你的保证:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 2015-02-17
    • 2012-10-01
    相关资源
    最近更新 更多