Boost.Asio async_send问题

Mar*_*lon 6 c++ boost-asio

我正在使用Boost.Asio来编写我正在编写的服务器应用程序.

async_send要求调用者保持正在发送的数据的所有权,直到数据成功发送.这意味着我的代码(看起来像下面这样)会失败,而且它会失败,因为data它将不再是一个有效的对象.

void func()
{
    std::vector<unsigned char> data;

    // ...
    // fill data with stuff
    // ...

    socket.async_send(boost::asio::buffer(data), handler);
}
Run Code Online (Sandbox Code Playgroud)

所以我的解决方案是做这样的事情:

std::vector<unsigned char> data;

void func()
{        
    // ...
    // fill data with stuff
    // ...

    socket.async_send(boost::asio::buffer(data), handler)
}
Run Code Online (Sandbox Code Playgroud)

但现在我想知道我是否有多个客户端,我是否需要为每个连接创建一个单独的向量?

或者我可以使用那个单一的载体吗?如果我能够使用那个单一的向量,如果我覆盖其中的内容会弄乱我发送给我所有客户端的数据吗?

Eug*_*nca 13

一个可能的解决方法是使用a shared_ptr来保存你的本地vector并更改处理程序的签名以接收一个,shared_ptr以便延长data发送完成之前的生命(感谢Tim指出这一点):

void handler( boost::shared_ptr<std::vector<char> > data )
{
}

void func()
{
    boost::shared_ptr<std::vector<char> > data(new std::vector<char>);
    // ...
    // fill data with stuff
    // ...

    socket.async_send(boost::asio::buffer(*data), boost:bind(handler,data));
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*ter 6

我通过将一个shared_ptr数据传递给处理函数来解决了类似的问题.由于asio在调用之前保留了处理程序仿函数,并且hander仿函数保留了shared_ptr引用,因此只要有一个打开的请求,数据就会保持分配状态.

编辑 - 这是一些代码:

这里连接对象保持正在写入的当前数据缓冲区,因此shared_ptr是连接对象,并且bind调用将方法仿函数附加到对象引用,并且asio调用使对象保持活动状态.

关键是每个处理程序必须使用另一个引用启动新的asyc操作,否则连接将被关闭.一旦完成连接或发生错误,我们就会停止生成新的读/写请求.需要注意的是,您需要确保在所有回调中检查错误对象.

boost::asio::async_write(
    mSocket,
    buffers,
    mHandlerStrand.wrap(
        boost::bind(
            &TCPConnection::InternalHandleAsyncWrite,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred)));

void TCPConnection::InternalHandleAsyncWrite(
    const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
Run Code Online (Sandbox Code Playgroud)


Sam*_*ler 5

但现在我想知道我是否有多个客户端,我是否需要为每个连接创建一个单独的向量?

是的,尽管每个向量不需要在全局范围内.此问题的典型解决方案是保留buffer作为对象的成员,并将该对象的成员函数绑定到传递给async_write完成处理程序的仿函数.这样,缓冲区将在异步写入的整个生命周期内保留在范围内.asio 示例充斥着使用this和使用绑定成员函数的这种用法shared_from_this.一般来说,优选的是使用shared_from_this以简化对象的寿命,尤其是在面部io_service:stop()~io_service().虽然对于简单的例子,这种脚手架通常是不必要的.

上述销毁序列允许程序通过使用shared_ptr <>来简化其资源管理.如果对象的生命周期与连接的生命周期(或其他一些异步操作序列)相关联,则对象的shared_ptr将绑定到与其关联的所有异步操作的处理程序中.

一个好的起点是异步回显服务器,因为它简单.

boost::asio::async_write(
    socket,
    boost::asio::buffer(data, bytes_transferred),
    boost::bind(
        &session::handle_write,
        this,
        boost::asio::placeholders::error
    )
);
Run Code Online (Sandbox Code Playgroud)