Boost.Asio - 具有自定义缓冲区的多个缓冲区

Posted

技术标签:

【中文标题】Boost.Asio - 具有自定义缓冲区的多个缓冲区【英文标题】:Boost.Asio - Multiple buffers with custom buffer 【发布时间】:2014-10-05 10:37:51 【问题描述】:

我正在编写一种 tcp 服务器。我正在使用 Boost.Asio,shared_const_buffer。

现在我必须写多个缓冲区。所以我是这样写的:

std::vector<shared_const_buffer> bufs;
bufs.push_back(buf1);
bufs.push_back(buf2);
...
boost::asio::async_write(*pSock, bufs, []  ... );

但是,我可以看到一个错误。

d:\ boost_1_56_0 \升压\ ASIO \详细\ consuming_buffers.hpp(175):错误C2679:이항 '=':오른쪽피연산자로 'shared_const_buffer' 형식을사용하는연산자가없거나허용되는변환이없습니다

嗯,我的 Visual Studio 不是英文版>o

d:\boost_1_56_0\boost\asio\detail\sumption_buffers.hpp(175): 错误 C2679: 二元运算符 '=' : 没有使用 shared_const_buffer 类型作为右侧的运算符或允许的转换。

我不确定我的翻译是否正确,但我认为您可以理解。反正我是看到boost\asio\detail\consuming_buffers.hpp(175)来解决问题的。

if (!at_end_)

  first_ = *buffers_.begin(); // <-- here's error point
  ++begin_remainder_;

所以我尝试在shared_const_buffer 中添加强制转换操作符,效果很神奇。

这是我的mcve

#include <iostream>
#include <vector>
#include <memory>

#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class shared_const_buffer

private:
    std::shared_ptr<std::vector<char> > m_pData;
    boost::asio::const_buffer m_buffer;

public:
    explicit shared_const_buffer(const std::vector<char> &data)
        : m_pData  std::make_shared<std::vector<char> >(data) 
        , m_buffer  boost::asio::buffer(*m_pData) 
    

    

    typedef boost::asio::const_buffer value_type;
    typedef const boost::asio::const_buffer *const_iterator;
    const boost::asio::const_buffer *begin() const  return &m_buffer; 
    const boost::asio::const_buffer *end() const  return &m_buffer + 1; 

    // it'll work if you uncomment this line.
    //operator const boost::asio::const_buffer &() const  return *begin(); 
;

void run_accept(boost::asio::io_service &iosrv, tcp::acceptor &acpt);

int main()

    boost::asio::io_service iosrv;

    tcp::acceptor acpt(iosrv, tcp::endpoint(tcp::v4(), 12345));
    run_accept(iosrv, acpt);

    iosrv.run();


void run_accept(boost::asio::io_service &iosrv, tcp::acceptor &acpt)

    auto pSock = std::make_shared<tcp::socket>(iosrv);
    acpt.async_accept(*pSock,
        [&, pSock](const boost::system::error_code &ec) 
            run_accept(iosrv, acpt);

            std::vector<shared_const_buffer> bufs;
            bufs.push_back(shared_const_buffer( 'a', 'b', 'c', 'd' ));
            bufs.push_back(shared_const_buffer( 'e', 'f', 'g', 'h' ));

            boost::asio::async_write(*pSock, bufs,
                [pSock](const boost::system::error_code &ec, size_t size) 
                    pSock->close();
                );
        );

但是,我不知道为什么它不起作用。 According to documentation,

缓冲区和 Scatter-Gather I/O

要使用多个缓冲区读取或写入(即 scatter-gather I/O),可以将多个缓冲区对象分配到支持 MutableBufferSequence(用于读取)或 ConstBufferSequence(用于写入)概念的容器中:

char d1[128];
std::vector<char> d2(128);
boost::array<char, 128> d3;

boost::array<mutable_buffer, 3> bufs1 = 
  boost::asio::buffer(d1),
  boost::asio::buffer(d2),
  boost::asio::buffer(d3) ;
bytes_transferred = sock.receive(bufs1);

std::vector<const_buffer> bufs2;
bufs2.push_back(boost::asio::buffer(d1));
bufs2.push_back(boost::asio::buffer(d2));
bufs2.push_back(boost::asio::buffer(d3));
bytes_transferred = sock.send(bufs2);

另外documentation 说这5行足以满足“ConstBufferSequence”。

// Implement the ConstBufferSequence requirements.
typedef boost::asio::const_buffer value_type;
typedef const boost::asio::const_buffer* const_iterator;
const boost::asio::const_buffer* begin() const  return &buffer_; 
const boost::asio::const_buffer* end() const  return &buffer_ + 1; 

我错过了什么?我正在使用 Visual Studio 2013 Update 3 和 boost 1.56.0。

【问题讨论】:

你能告诉我哪一行导致了上述错误吗? @LajosArpad 错误发生在first_ = *buffers_.begin();。编译器还注意到boost::asio::async_write(*pSock, bufs, ... 【参考方案1】:

微妙的细节是std::vector&lt;shared_const_buffer&gt; 被传递给write() 操作,因此它必须支持ConstBufferSequence 概念。 shared_const_buffer 满足 ConstBufferSequence 的类型要求,std::vector&lt;shared_const_buffer&gt; 不满足 ConstBufferSequence 的类型要求。 ConstBufferSequence 的要求之一是对于X 的类型,X::value_type 是满足ConvertibleToConstBuffer 类型要求的类型。基本上,const_buffer 的实例必须可以从 X::value_type 构造并从 X::value_type 分配:

X::value_type a;
boost::asio::const_buffer u(a);
u = a;

std::vector&lt;shared_const_buffer&gt;的情况下,value_typeshared_const_buffershared_const_buffer既不能用于构造const_buffer,也不能分配给const_buffer。因此,产生的编译错误。

【讨论】:

好时机。我刚刚发布了我的答案。我想现在不能不 +1 :)【参考方案2】:

async_write 采用ConstBufferSequence。根据文档,这个概念需要满足的第一个要求是:

在您的示例中,std::vector&lt;shared_const_buffer&gt;::value_type 的计算结果为 shared_const_buffer,这意味着它需要建模 ConvertibleToConstBuffer。通过添加转换,您完全可以满足这一点。

【讨论】:

哈,当然是好时机。 (: @sehe 和 Tanner:伏尔泰说 'les beaux esprits se rencontrent' !直译为“志同道合”…… @John06 我的看法:“伟大的头脑阅读文档”+“Tanner 监视器 boost-asio”+“sehe 监视器 boost-...”。时间不能用心灵的美丽来解释:)

以上是关于Boost.Asio - 具有自定义缓冲区的多个缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

boost::asio::io_context::run_one_for() 发送大缓冲区失败

试图了解 Boost.Asio 自定义服务实现

为啥 boost::asio::read 缓冲区数据大小小于读取大小?

Boost::Asio::Read 没有填充缓冲区

使用 boost-asio 时实时将缓冲区写入磁盘

boost::asio 数据拥有`ConstBufferSequence`