简体   繁体   English

uv_start_read on windows named pipe 客户端等待直到服务器关闭其 pipe 并导致 EOF

[英]uv_start_read on windows named pipe client waits until the server closes its pipe and results in EOF

I have two programs, one that I've written and works as a pipe server and uses io completion ports.我有两个程序,一个是我编写的,作为 pipe 服务器运行,使用 io 完成端口。 the other isn't written by me but it's open source and it uses libuv heavily for its async processing.另一个不是我写的,但它是开源的,它大量使用 libuv 进行异步处理。

now I want to edit this program to add the pipe functionality through libuv and to be able to contact the server.现在我想编辑这个程序以通过 libuv 添加 pipe 功能并能够联系服务器。

I can connect to the server using uv_pipe_connect and I get the connect callback triggered, then I start reading with uv_read_start which returns 0 (no error) so I expect the allocation callback and read callback get triggered once the server writes to the client.我可以使用uv_pipe_connect连接到服务器并触发连接回调,然后我开始使用返回 0(无错误)的uv_read_start读取,所以我希望一旦服务器写入客户端就会触发分配回调和读取回调。

however when the server writes some bytes and I receive a notification through iocp that an amount of bytes were written, the client doesn't receive anything and no any callbacks are invoked.但是,当服务器写入一些字节并且我通过 iocp 收到一个通知,告知已写入一定数量的字节时,客户端不会收到任何内容,也不会调用任何回调。 And on closing the server process the read callback is invoked with error EOF并且在关闭服务器进程时调用读取回调,错误为EOF

this is the libuv related code I'm using:这是我正在使用的 libuv 相关代码:

class IPipeListener;

class PipeClient
{

public:

    PipeClient(IPipeListener* listener, const std::string& pipe_name);

    ~PipeClient();

    void stop();

private:

    static void onAllocBuff(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);

    static void onConnect(uv_connect_t *connect_req, int result);

    static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);

    static void onWrite(uv_write_t* req, int result);

    // a pod structure used to read and write data 
    PipeCommand command;
    IPipeListener* m_listener = nullptr;
    uv_pipe_t m_pipe;
    uv_connect_t m_connect;
    uv_read_t read_req;
    uv_write_t write_req;
};

PipeClient::PipeClient(IPipeListener* listener, const std::string& pipe_name)
{
    if (!listener || pipe_name.empty())
        return;
    m_listener = listener;
    uv_pipe_init(uv_default_loop(), &m_pipe, 1);
    m_connect.data = this;
    write_req.data = this;
    read_req.data = this;
    uv_pipe_connect(&m_connect, &m_pipe, pipe_name.c_str(), onConnect);
}

void PipeClient::onAllocBuff(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
    MessageBoxA(0, "onAllocBuff", "onAllocBuff", 0);
    auto pipe = static_cast<PipeClient*>(handle->data);
    buf->base = reinterpret_cast<char*>(&pipe->command);
    buf->len = sizeof(pipe->command);
}

void PipeClient::onConnect(uv_connect_t* connect_req, int result)
{
    MessageBoxA(0, "onConnect", "onConnect", 0);
    auto pipe = static_cast<PipeClient*>(connect_req->data);
    if (result < 0)
    {
        pipe->command.code = PipeCommand::OpCode::Error;
        pipe->m_listener->onPipeCommand(pipe->command);
        return;
    }
    MessageBoxA(0, "starting read", "notify", 0);
    int r = uv_read_start(connect_req->handle, onAllocBuff, onRead);
    if (r != 0)
    {
        std::string err_msg = "failed to start reading with error : ";
        err_msg += uv_err_name(r);
        MessageBoxA(0, err_msg.c_str(), "error", 0);
    }
}

void PipeClient::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
    MessageBoxA(0, "onRead", "onRead", 0);
    auto pipe = static_cast<PipeClient*>(stream->data);
    uv_read_stop(stream);
    if (nread < 0)
    {
        std::string err_msg = "failed to read with error : ";
        err_msg += uv_err_name(nread);
        MessageBoxA(0, err_msg.c_str(), "error", 0);
        pipe->command.code = PipeCommand::OpCode::Error;
        pipe->m_listener->onPipeCommand(pipe->command);
        return;
    }

    pipe->m_listener->onPipeCommand(pipe->command);
    uv_buf_t write_buff;
    write_buff.base = reinterpret_cast<char*>(&pipe->command);
    write_buff.len = sizeof(pipe->command);
    uv_write(&pipe->write_req,
        stream, &write_buff, 1, onWrite);
}

I had to set the ipc flag to 0 in uv_pipe_init and set the data of m_pipe to point to my PipeClient class.我必须在 uv_pipe_init 中将 ipc 标志设置为 0, uv_pipe_init的数据设置为指向我的m_pipe PipeClient

from here: https://github.com/libuv/libuv/blob/v1.x/src/win/pipe.c从这里: https://github.com/libuv/libuv/blob/v1.x/src/win/pipe.c

I saw that the pipe reads writes aren't ordinary iocp reads writes if the ipc flag is set, instead the take another methods that I didn't want如果设置了 ipc 标志,我看到 pipe 读写不是普通的 iocp 读写,而是采用我不想要的其他方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM