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

时间:2014-10-05 10:37:52

标签: c++ boost boost-asio

我正在编写一种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 \ boost \ asio \ detail \ consume_buffers.hpp(175):错误C2679:이항'=':오른쪽피연산자로'shared_const_buffer'형식을사용하는연산자가없거나허용되는변환이없습니다。

嗯,我的Visual Studio不是英文版&gt; o&lt;这是我的翻译

  

d:\ boost_1_56_0 \ boost \ asio \ detail \ consume_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

  

缓冲区和分散 - 收集I / O

     

要使用多个缓冲区读取或写入(即分散 - 收集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并提升1.56.0。

2 个答案:

答案 0 :(得分:5)

细微的细节是std::vector<shared_const_buffer>被传递给write()操作,因此它必须支持ConstBufferSequence概念。虽然shared_const_buffer符合ConstBufferSequence的类型要求,但std::vector<shared_const_buffer>无法满足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<shared_const_buffer>value_typeshared_const_buffer,而shared_const_buffer既不能用于构建const_buffer也不能用于const_buffer }。因此,导致编译错误。

答案 1 :(得分:4)

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

enter image description here

在您的示例中,std::vector<shared_const_buffer>::value_type评估为shared_const_buffer,这意味着它需要对ConvertibleToConstBuffer进行建模。通过添加转换,您可以完全满足。