boost::asio::async_read 一直在命名管道上返回 eof

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

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

发送 EOF 是因为写入器在完成写入管道后将其关闭。我想继续阅读。这就是为什么我在 on_read 中调用 pipe.async_wait()。但是,即使没有准备好从管道中读取任何内容,on_read 也会调用 my_pipe::async_read(),后者会再次用 bytes = 0ec=EOF 调用 on_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_read\n";
    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 << "eof\n";
        std::cout << "call async_read\n";
        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();
}

感谢您的帮助。

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

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

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