我的boost asio async_read是否获得了比赛条件?

Aba*_*oub -2 c++ boost race-condition boost-asio

bool Connection::Receive(){
    std::vector<uint8_t> buf(1000);
    boost::asio::async_read(socket_,boost::asio::buffer(buf,1000),
            boost::bind(&Connection::handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

    int rcvlen=buf.size();
    ByteBuffer b((std::shared_ptr<uint8_t>)buf.data(),rcvlen);
    if(rcvlen <= 0){
        buf.clear();
        return false;
    }
    OnReceived(b);
    buf.clear();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

该方法工作正常,但仅当我在其中创建断点时才有效。等待接收的时间是否有问题?没有断点,什么也收不到。

xDD*_*xDD 5

您试图在启动异步操作后立即从接收缓冲区读取数据,而不等待它完成,这就是为什么在设置断点时它可以工作的原因。

async_read之后的代码属于Connection::handler,因为这是您告诉async_read接收一些数据后调用的回调。

您通常需要一个start_read和一个handle_read_some功能:

void connection::start_read()
{
    socket_->async_read_some(boost::asio::buffer(read_buffer_),
        boost::bind(&connection::handle_read_some, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
}

void connection::handle_read_some(const boost::system::error_code& error, size_t bytes_transferred)
{
    if (!error)
    {
        // Use the data here!

        start_read();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意shared_from_this,如果您希望通过未完成的I / O请求数来自动处理连接的生命周期,则这一点很重要。确保从派生您的类,boost::enable_shared_from_this<connection>并仅使用创建它make_shared<connection>

为了实现这一点,您的构造函数应该是私有的,您可以添加一个朋友声明(C ++ 0x版本;如果编译器不支持此声明,则您必须自己插入正确数量的参数):

template<typename T, typename... Arg> friend boost::shared_ptr<T> boost::make_shared(const Arg&...);
Run Code Online (Sandbox Code Playgroud)

还要确保在调用回调时您的接收缓冲区仍处于活动状态,最好使用连接类的静态大小的缓冲区成员变量。