使用Boost Asio对文件描述符进行异步等待

32

我正在尝试将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));
}

但是处理程序立即被调用,表示没有任何字节可以读取。我希望它只在有东西可读时才被调用,但是boost::asio不能读取它。它应该像一个增强版本的select()一样工作。有简单的方法吗?

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


你使用的是哪个 D-Bus API?是底层的 C API 吗? - Craig McQueen
1个回答

34

这正是null_buffers设计的问题。

有时程序必须与想要自己执行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));
  }
}

文档中还包括一个优秀的示例


这正是我正在寻找的。它完美地集成了。非常感谢! - Edu Felipe
1
嗨,Sam,你能更详细地解释一下你提到的文档中包含的优秀示例吗?我想使用third_party_lib.session来读取/异步读取/写入/异步写入一些内容,我该怎么做呢?我还不是很清楚。实际上,模拟第三方库的示例让我感到困惑。谢谢。 - Peter Lee
@Peter,请提出一个新问题,包括你觉得哪个部分令人困惑。 - Sam Miller
@Sam,我发布了另一个问题:https://dev59.com/0lrUa4cB1Zd3GeqPm8Ak 请查看一下。谢谢。 - Peter Lee
我曾这样使用libcurl的async_read_some,但遇到一个问题,当服务器关闭套接字时,它会在没有错误的情况下返回,并且boost/asio套接字仍然认为它是打开的。我改用async_receive,使用message_peek标志和大小为1的缓冲区来检测EOF。 - Peter Tseng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接