PIPE_NOWAIT打破了连接

PIPE_NOWAIT breaks connetion

本文关键字:连接 NOWAIT PIPE      更新时间:2023-10-16

我有这段代码,它代表简单的管道服务器。当我设置PIPE_NOWAIT属性然后尝试使用 CreateFile 函数从客户端连接到它时 - 没有任何反应,我们仍然在第二个块中。当我删除PIPE_NOWAIT标志时 - 我们挂在 ConnectNamedPipe 函数中,从客户端调用 CreateFile 后,我们进入第一个块,这意味着我们成功了。为什么会这样?

HANDLE hPipe;
std::string msg;
DWORD dwRead;
hPipe = CreateNamedPipe(L"\\.\pipe\Pipe100500",
PIPE_ACCESS_DUPLEX,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (true)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE)
{
// Waiting in the ConnectNamedPipe and then we are here
}
else
{
// always here when PIPE_NOWAIT
}
}

根据CreateNamedPipe()文档:


PIPE_NOWAIT 0x00000001

非阻塞模式已启用。在这种模式下,ReadFileWriteFileConnectNamedPipe总是立即返回

根据ConnectNamedPipe()文档:

如果指定的管道句柄处于非阻塞模式,则ConnectNamedPipe始终立即返回。在非阻塞模式下,ConnectNamedPipe首次为与以前的客户端断开连接的管道实例调用该值时返回非零值。这表示管道现在可以连接到新的客户端进程。在管道手柄处于非阻塞模式的所有其他情况下,ConnectNamedPipe返回零。在这些情况下,如果未连接客户端,GetLastError返回ERROR_PIPE_LISTENING,如果客户端已连接,则ERROR_PIPE_CONNECTED返回,如果以前的客户端已关闭其管道句柄但服务器尚未断开连接,则返回ERROR_NO_DATA请注意,只有在收到ERROR_PIPE_CONNECTED错误后,客户端和服务器之间才存在良好的连接

注意:支持非阻塞模式以兼容Microsoft LAN 管理器版本 2.0,并且不应使用它来实现与命名管道的异步输入和输出 (I/O)。

因此,要正确使用PIPE_NOWAIT(即使你真的根本不应该使用它!),你需要更多类似的东西:

HANDLE hPipe;
std::string msg;
DWORD dwRead;
hPipe = CreateNamedPipe(L"\\.\pipe\Pipe100500",
PIPE_ACCESS_DUPLEX,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
while (true)
{
if (ConnectNamedPipe(hPipe, NULL))
{
// pipe has been disconnected and is now available to be connected to again...
}
else
{
switch (GetLastError())
{
case ERROR_PIPE_LISTENING:
// no client is connected...
break;
case ERROR_PIPE_CONNECTED:
// a client is now connected...
break;
case ERROR_NO_DATA:
// a previous client has closed its pipe handle but the server has not disconnected yet...
DisconnectNamedPipe(hPipe);
break;
default:
// fatal error...
break;
}
}
}
}

否则,请按照文档所说的进行操作,根本不要使用PIPE_NOWAIT。 如果不希望阻塞ConnectNamedPipe(),请改用重叠 I/O。 MSDN 提供了以下示例:

使用重叠 I/O 的命名管道服务器

使用完成例程的命名管道服务器