uv_start_read 在 windows 命名管道客户端等待,直到服务器关闭其管道并导致 EOF
uv_start_read on windows named pipe client waits until the server closes its pipe and results in EOF
我有两个程序,一个是我编写的,用作管道服务器并使用 io 完成端口。
另一个不是我写的,但它是开源的,它大量使用 libuv 进行异步处理。
现在我想编辑此程序以通过 libuv 添加管道功能并能够联系服务器。
我可以使用 uv_pipe_connect
连接到服务器并触发连接回调,然后我开始使用 uv_read_start
读取 returns 0(无错误)所以我希望一旦服务器写入客户端,就会触发分配回调和读取回调。
然而,当服务器写入一些字节并且我通过 iocp 收到一个通知,告知写入了一定数量的字节时,客户端没有收到任何东西,也没有调用任何回调。在关闭服务器进程时,调用读取回调时出现错误 EOF
这是我使用的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);
}
我必须在 uv_pipe_init
中将 ipc 标志设置为 0,并将 m_pipe
的数据设置为指向我的 PipeClient
class .
从这里开始:
https://github.com/libuv/libuv/blob/v1.x/src/win/pipe.c
我看到如果设置了 ipc 标志,管道读写不是普通的 iocp 读写,而是采用我不想要的另一种方法
我有两个程序,一个是我编写的,用作管道服务器并使用 io 完成端口。 另一个不是我写的,但它是开源的,它大量使用 libuv 进行异步处理。
现在我想编辑此程序以通过 libuv 添加管道功能并能够联系服务器。
我可以使用 uv_pipe_connect
连接到服务器并触发连接回调,然后我开始使用 uv_read_start
读取 returns 0(无错误)所以我希望一旦服务器写入客户端,就会触发分配回调和读取回调。
然而,当服务器写入一些字节并且我通过 iocp 收到一个通知,告知写入了一定数量的字节时,客户端没有收到任何东西,也没有调用任何回调。在关闭服务器进程时,调用读取回调时出现错误 EOF
这是我使用的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);
}
我必须在 uv_pipe_init
中将 ipc 标志设置为 0,并将 m_pipe
的数据设置为指向我的 PipeClient
class .
从这里开始: https://github.com/libuv/libuv/blob/v1.x/src/win/pipe.c
我看到如果设置了 ipc 标志,管道读写不是普通的 iocp 读写,而是采用我不想要的另一种方法