【问题标题】:boost::asio asynchronous operations and resourcesboost::asio 异步操作和资源
【发布时间】:2011-09-03 19:26:37
【问题描述】:

所以我创建了一个使用 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 是一个很好的问题,但将来我建议在 Stackoverflow 上将其拆分为单独的问题。

标签: c++ boost asynchronous boost-asio


【解决方案1】:

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

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

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

下一次调用 doRead 应该在处理读取之前还是之后 数据?好像如果放在do_something()之前,程序 可以立即开始读取另一个数据包,如果它放在后面, 线程被捆绑做任何 do_something 做的事情,这可能 可能需要一段时间。

这真的取决于do_something() 需要与m_recvBuffer 做什么。如果您希望使用io_service::post()doRead() 并行调用do_something(),您可能需要复制m_recvBuffer

如果我将 doRead() 放在处理之前,是否 这意味着 m_readBuffer 中的数据在我处理时可能会发生变化?

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-05
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多