Boost.Asio-轮询命名管道 [英] Boost.Asio - polling a named pipe

查看:78
本文介绍了Boost.Asio-轮询命名管道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to listen for input on a named pipe. I'm using Boost.Asio's stream_descriptor and async_read under Linux. The problem is, the call to io_service::run() only blocks like I want it to until the first read. After that, it just keeps calling the handler immediately with the "End of file" error, even though I try to attach more async_reads to it. The code I have is equivalent to the following:

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会立即返回.我发现使它像我想要的那样工作的唯一方法是关闭并重新打开命名管道,但这似乎是一种hack:

Only the first async_read works as I expect it to. Subsequent async_reads just return immediately. The only way I found to make it work like I want is to close and reopen the named pipe, but it seems like a hack:

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);
}

有人可以告诉我我在做什么错吗?

Can anyone tell me what am I doing wrong?

更新:这是一个简单的读取"版本,该版本可以简化一些代码,问题仍然存在:

UPDATE: Here's a simple "read" version, which allowed for some code simplification, the problem remains the same:

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()(根据文档).

This is not how works. run() is not intended to be called in a loop. If you insist, you need to call reset() in between (as per the documentation).

此外,如果您/想要/阻止行为,为什么还要使用 async _ * 接口?

Also, if you /want/ blocking behaviour, why are you using the async_* interface?

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

  1. Consider using a simple iostream to read the fd:

在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 :

  • Or if you must attach to some fd you get from somewhere else, use file_descriptor from Boost IOstreams:

    在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";
        }
    }
    

  • 两个示例均显示预期结果:

    Both examples print the expected:

    word: 1 hello
    word: 2 world
    

    这篇关于Boost.Asio-轮询命名管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆