boost :: asio异步操作和资源

时间:2011-09-03 19:26:37

标签: c++ boost asynchronous boost-asio

所以我创建了一个socket类,它使用boost :: asio库来进行异步读写。它有效,但我有几个问题。

这是一个基本的代码示例:

class Socket
{
public:
    void doRead()
    {
        m_sock->async_receive_from(boost::asio::buffer(m_recvBuffer), m_from, boost::bind(&Socket::handleRecv, this, boost::asio::placeholders::error(), boost::asio::placeholders::bytes_transferred()));
    }

    void handleRecv(boost::system::error_code e, int bytes)
    {
        if (e.value() || !bytes)
        {
            handle_error();
            return;
        }
        //do something with data read
        do_something(m_recvBuffer);

        doRead(); //read another packet
    }

protected:
    boost::array<char, 1024> m_recvBuffer;
    boost::asio::ip::udp::endpoint m_from;
};

程序似乎会读取数据包,处理它,然后准备读取另一个数据包。简单。 但是,如果我设置一个线程池呢?下一次调用doRead()是在处理读取数据之前还是之后?似乎如果它放在do_something()之前,程序可以立即开始读取另一个数据包,如果它被放在后面,那么线程就会做do_something()所做的任何事情,这可能需要一段时间。如果我在处理之前放置doRead(),这是否意味着我在处理它时m_readBuffer中的数据可能会发生变化?

另外,如果我正在使用async_send_to(),我是否应该将要发送的数据复制到临时缓冲区中,因为实际发送可能要么在数据超出范围之后才会发生?即。

void send()
{
    char data[] = {1, 2, 3, 4, 5};
    m_sock->async_send_to(boost::buffer(&data[0], 5), someEndpoint, someHandler);
} //"data" gets deallocated, but the write might not have happened yet!

此外,当套接字关闭时,将调用handleRecv并显示错误,指示它已被中断。如果我做

Socket* mySocket = new Socket()...
...
mySocket->close();
delete mySocket;

是否会导致错误,因为在调用/完成mySocket之前有可能会删除handleRecv()

1 个答案:

答案 0 :(得分:2)

这里有很多问题,我会尝试一次解决这些问题。

  

但是如果我设置一个线程池呢?

在Boost.Asio中使用线程池的传统方法是调用io_service::run() from multiple threads。请注意,这不是一个通用的答案,但可能存在可扩展性或性能问题,但这种方法是迄今为止最容易实现的方法。 Stackoverflow上有许多类似的questions,包含更多信息。

  

在处理读取之前或之后,下一次调用doRead是否应该   数据?看来如果它放在do_something()之前,程序   可以立即开始读取另一个数据包,如果放在后面,   做任何do_something所做的事情就可以了   可能需要一段时间。

这实际上取决于do_something()m_recvBuffer需要做什么。如果您希望使用do_something()doRead()同时调用io_service::post(),则可能需要复制m_recvBuffer

  

如果我在处理之前放了doRead(),那么   这意味着当我处理它时,m_readBuffer中的数据可能会改变吗?

正如我之前提到的,是的,这可以并且将会发生。

  

另外,如果我使用的是async_send_to(),我是否应该复制要发送的数据   进入临时缓冲区,因为实际发送可能不会发生   直到数据超出范围后?

作为documentation describes,由调用者(您)来确保缓冲区在异步操作期间保持在作用域内。如您所料,您当前的示例调用未定义的行为,因为data[]将超出范围。

  

此外,当套接字关闭时,将调用handleRecv()   错误表明它被中断了。

如果您希望继续使用套接字,请使用cancel()进行interrupt outstanding异步操作。否则,close()将起作用。在任一场景中传递给未完成的异步操作的错误是boost::asio::error::operation_aborted