我试图在命名管道上侦听输入。我在Linux下使用Boost.Asio的stream_descriptorasync_read。问题是,对io_service::run()的调用只会像我希望的那样阻塞,直到第一次读取为止。此后,即使我尝试附加更多async_reads,它也始终会立即显示“文件结尾”错误,立即调用处理程序。我拥有的代码等效于以下代码:

boost::asio::io_service io_service;
int fifo_d = open("/tmp/fifo", O_RDONLY);
boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
while (true)
{
    // buffer and handler probably aren't important for the purposes of this question
    boost::asio::async_read(fifo, buffer, handler);
    io_service.run();
}

正如我期望的那样,只有第一个async_read可以工作。随后的async_reads会立即返回。我发现使它像我想要的那样工作的唯一方法是关闭并重新打开命名管道,但这似乎很简单:
boost::asio::io_service io_service;
while (true)
{
    int fifo_d = open("/tmp/fifo", O_RDONLY);
    boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
    boost::asio::async_read(fifo, buffer, handler);
    io_service.run();
    close(fifo_d);
}

谁能告诉我我在做什么错?

更新:这是一个简单的“读取”版本,该版本允许一些代码简化,问题仍然存在:
int fifo_d = open("/tmp/fifo", O_RDONLY);
boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
while (true) {
    try {
        boost::asio::read(fifo, boost::asio::buffer(buffer));
    }
    catch (boost::system::system_error& err) {
        // It loops here with "read: End of file" error
        std::cout << err.what() << std::endl;
    }
}

最佳答案

这不是工作方式。不应在循环中调用run()。如果您坚持要求,则需要在两者之间调用reset()(根据文档)。

另外,如果您/want/阻止了行为,为什么还要使用async_*接口(interface)?

演示版

  • 考虑使用简单的iostream读取fd:

    Live On Coliru
    #include <iostream>
    #include <fstream>
    
    int main() {
        std::ifstream fifo("/tmp/fifo");
    
        std::string word;
        size_t lineno = 0;
        while (fifo >> word) {
            std::cout << "word: " << ++lineno << "\t" << word << "\n";
        }
    }
    
  • 或者,如果您必须附加到从其他地方获得的某些fd,请使用Boost IOstreams中的file_descriptor:

    Live On Coliru
    #include <boost/iostreams/device/file_descriptor.hpp>
    #include <boost/iostreams/stream.hpp>
    #include <iostream>
    #include <fcntl.h>
    
    int main() {
        namespace io = boost::iostreams;
        using src = io::file_descriptor_source;
        io::stream<src> fifo(src(open("./fifo", O_RDONLY), io::file_descriptor_flags::close_handle));
    
        std::string word;
        size_t number = 0;
        while (fifo >> word) {
            std::cout << "word: " << ++number << "\t" << word << "\n";
        }
    }
    

  • 这两个示例均显示预期结果:
    word: 1 hello
    word: 2 world
    

    10-02 04:55