Boost.Asio - 轮询命名管道
Boost.Asio - polling a named pipe
我正在尝试侦听命名管道上的输入。我在Linux下使用Boost.Asio的stream_descriptor和async_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()
(根据文档)。
另外,如果你/想要/阻止行为,你为什么要使用async_*
界面?
演示
-
考虑使用简单的iostream来读取fd:
住在科里鲁
#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
:住在科里鲁
#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
正如sehe报道的那样,这不是boost::asio的工作方式。ioservice::run()
方法在阻止模式下运行,同时它有一些工作。当 ioservice 停止工作时,您必须在放置其他工作之前调用 reset()
方法,这就是为什么在您的第一个代码中async_read只执行一次。
在这种情况下,常见模式如下所示:
void handler(...) {
if (!error) {
// do your work
boost::asio::async_read(fifo, buffer, handler); // <-- at the end of the handler a subsequent async_read is put to the ioservice, so it never goes out-of-work
}
}
boost::asio::io_service io_service;
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); // <-- you call async_read only once here.
io_service.run(); //<-- this blocks till an error occurs
- 理解boost::asio-async_read在无需读取内容时的行为
- 提升 ASIO 无法识别计时器对象
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- IPC使用多个管道和分支进程来运行Python程序
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::asio如何生成多个协同程序,然后加入它们
- 缓慢提升ASIO
- 从 Boost ASIO 获取 epoll 描述符 io_service对象
- 如何在 Boost.Asio 中使用 Zero-copy sendmsg/receive
- C++ Boost::asio串行通信与Arduino无法写入
- 如何创建函数管道,以便函数一个接一个地运行?
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- boost::asio::async_read 在命名管道上不断返回 EOF
- 由于管道破裂,提升 asio 发送消息失败
- 为什么 read() 在管道连接到使用 boost::asio for STDIN/STDOUT 的程序时,使用 EAG
- Boost Asio:尝试调用写入函数时管道破裂"externaly"
- Boost.Asio - 轮询命名管道
- boost asio async_write未在断开连接的客户端上生成管道破裂或其他错误
- 使用 Boost::asio posix stream_descriptor读取 ftrace 管道