【问题标题】:Async wait on file descriptor using Boost Asio使用 Boost Asio 异步等待文件描述符
【发布时间】:2011-06-08 20:07:36
【问题描述】:

我正在尝试将 D-Bus 与我的 boost::asio 应用程序集成。

D-Bus 有一个 API 可以枚举一组 Unix 文件描述符(主要是套接字,但也可以是 FIFO)以进行监视。 当这些描述符有东西要读取时,我应该通知 D-Bus API,以便它可以读取它们并执行它。

目前我正在这样做:

using boost::asio::posix::stream_descriptor;
void read_handle(stream_descriptor* desc, const boost::system::error_code& ec,
                 std::size_t bytes_read)
{
    if (!ec) {
        stream_descriptor::bytes_readable command(true);
        descriptor->io_control(command);
        std::size_t bytes_readable = command.get();
        std::cout << "It thinks I should read" << bytes_readable
            << " bytes" << std::endl;
    } else {
        std::cout << "There was an error" << std::endl;
    }
}

void watch_descriptor(boost::asio::io_service& ios, int file_descriptor)
{
    // Create the asio representation of the descriptor
    stream_descriptor* desc = new stream_descriptor(ios);
    desc->assign(file_descriptor);

    // Try to read 0 bytes just to be informed that there is something to be read
    std::vector<char> buffer(0);
    desc->async_read_some(boost::asio::buffer(buffer, 0),
        boost::bind(read_handle, desc, _1, _2));
}

但是处理程序被立即调用,说它有 0 个字节要读取。我希望仅在有要阅读的内容时才调用它,但是 boost::asio 不能 阅读它。它应该就像一个美化的select()。有没有简单的方法来做到这一点?

PS:我在我的软件中广泛使用boost::asio,这只是其中的一小部分,所以我不想依赖glib 或其他主循环。

【问题讨论】:

  • 您使用的 D-Bus API 是什么?是低级 C API 吗?

标签: c++ boost boost-asio dbus


【解决方案1】:

这正是null_buffersdesigned 的问题。

有时必须集成一个程序 与想要的第三方库 自己执行 I/O 操作。 为了促进这一点,Boost.Asio 包括一个 null_buffers 类型,它可以 可用于读写 操作。一个 null_buffers 操作 直到 I/O 对象完成才返回 “准备好”执行操作。

例如,执行一个 非阻塞读取类似 可以使用以下:

ip::tcp::socket socket(my_io_service);
...
ip::tcp::socket::non_blocking nb(true);
socket.io_control(nb);
...
socket.async_read_some(null_buffers(), read_handler);
...
void read_handler(boost::system::error_code ec)
{
  if (!ec)
  {
    std::vector<char> buf(socket.available());
    socket.read_some(buffer(buf));
  }
}

文档中还包含一个excellent example

【讨论】:

  • 这正是我想要的。它完美地融合在一起。非常感谢!
  • 嗨,Sam,您能解释一下您提到的文档中包含的出色示例吗?我想使用third_party_lib.session 来读取/AsyncRead/Write/AsyncWrite 的东西,我该怎么做?我还不是很清楚。模拟 third_party_lib 的示例实际上让我感到困惑。谢谢。
  • @Peter 请提出一个新问题,包括示例的哪一部分让您感到困惑。
  • @Sam,我已经发布了另一个问题:*.com/questions/7235055/… 请检查一下。谢谢。
  • 我以这种方式将 async_read_some 与 libcurl 一起使用,但是当服务器关闭套接字时它返回没有错误,并且 boost/asio 套接字也仍然认为它是打开的。我使用 async_receive 代替 message_peek 标志和大小为 1 的缓冲区来检测 EOF。