我有一段代表简单管道服务器的代码。当我设置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
}
}
答案 0 :(得分:0)
根据CreateNamedPipe()
文档:
PIPE_NOWAIT
0x00000001启用非阻止模式。在此模式下,
ReadFile
,WriteFile
和ConnectNamedPipe
始终会立即返回。
根据ConnectNamedPipe()
文档:
如果指定的管道句柄处于非阻塞模式,
ConnectNamedPipe
始终会立即返回。在非阻塞模式下,ConnectNamedPipe
在第一次为与先前客户端断开连接的管道实例调用时返回非零值。这表明管道现在可以连接到新的客户端进程。 在管道处理处于非阻塞模式的所有其他情况下,ConnectNamedPipe
返回零。在这些情况下,GetLastError
如果没有连接客户端则返回ERROR_PIPE_LISTENING
,如果客户端已连接则返回ERROR_PIPE_CONNECTED
,如果之前的客户端已关闭其管道句柄但服务器ERROR_NO_DATA
没有断开连接。 请注意,只有在收到ERROR_PIPE_CONNECTED
错误后才能在客户端和服务器之间建立良好的连接。注意支持非阻塞模式以与Microsoft LAN Manager 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提供了以下示例: