boost::asio::async_read 在命名管道上不断返回 EOF

boost::asio::async_read keeps returning eof on named pipe

本文关键字:管道 返回 EOF async asio read boost      更新时间:2023-10-16

这是我在阅读模式下打开管道的示例代码。它使用boost::asio从管道读取。当数据(假设 X 字节)写入管道时,它会调用缓冲区中具有ec=EOFbytes=X和 X 字节数据的on_read

发送 EOF 是因为编写器在完成对管道的写入后将其关闭。我想继续阅读。这就是为什么我在on_read中称pipe.async_wait().但是,即使没有准备好从管道中读取任何内容,on_read调用my_pipe::async_read()再次调用带有bytes = 0ec=EOFon_read()。这在一个无限循环中持续下去。

为什么它一直反复阅读EOF

#include <boost/asio/io_service.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <unistd.h>
#include <chrono>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <boost/asio/read.hpp>
#include <boost/asio/write.hpp>
#include <boost/bind.hpp>

class my_pipe final
{
public:
explicit my_pipe(boost::asio::io_service& io_service);
~my_pipe();
private:
boost::asio::posix::stream_descriptor pipe;
std::vector<char> _buf{};
void async_read(const boost::system::error_code& ec);
void on_read(const boost::system::error_code& ec, std::size_t bytes_transferred);
};
my_pipe::my_pipe(boost::asio::io_service& io_service) : pipe(io_service)
{
int fd = open("/tmp/pipe1", O_RDONLY | O_NONBLOCK);
if (fd == -1)
return;
_buf.resize(8192);
pipe.assign(fd);
pipe.async_wait(boost::asio::posix::stream_descriptor::wait_read,
boost::bind(&my_pipe::async_read, this, boost::asio::placeholders::error));
}
my_pipe::~my_pipe()
{
pipe.close();
}
void my_pipe::async_read(const boost::system::error_code& ec)
{
std::cout << "async_readn";
if (ec)
return;
boost::asio::async_read(pipe, boost::asio::buffer(_buf),
boost::bind(&my_pipe::on_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void my_pipe::on_read(const boost::system::error_code& ec, std::size_t bytes)
{
std::cout << "on_read. bytes=" << bytes << "n";
if (!ec || ec == boost::asio::error::eof) {
if (ec == boost::asio::error::eof)
std::cout << "eofn";
std::cout << "call async_readn";
pipe.async_wait(boost::asio::posix::stream_descriptor::wait_read,
boost::bind(&my_pipe::async_read, this, boost::asio::placeholders::error));
} else {
std::cout << "on_read error: " << ec.message() << "n";
}
}
int main()
{
boost::asio::io_service ios;
my_pipe obj(ios);
ios.run();
}

感谢您的帮助。

当一端的所有手柄都关闭时,管道是"寡妇"的。

在这种情况下,在获得 EOF 后,应关闭管道手柄,然后重新打开管道。然后,您可以在新描述符上发出async_read()以等待更多数据。

如果您有多个编写器,还要考虑写入只能保证最多PIPE_BUF个字节的原子写入。