PIPE_NOWAIT 断开连接
PIPE_NOWAIT breaks connetion
我有一段代表简单管道服务器的代码。当我设置 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
Nonblocking mode is enabled. In this mode, ReadFile
, WriteFile
, and ConnectNamedPipe
always return immediately.
根据 ConnectNamedPipe()
文档:
If the specified pipe handle is in nonblocking mode, ConnectNamedPipe
always returns immediately. In nonblocking mode, ConnectNamedPipe
returns a nonzero value the first time it is called for a pipe instance that is disconnected from a previous client. This indicates that the pipe is now available to be connected to a new client process. In all other situations when the pipe handle is in nonblocking mode, ConnectNamedPipe
returns zero. In these situations, GetLastError
returns ERROR_PIPE_LISTENING
if no client is connected, ERROR_PIPE_CONNECTED
if a client is connected, and ERROR_NO_DATA
if a previous client has closed its pipe handle but the server has not disconnected. Note that a good connection between client and server exists only after the ERROR_PIPE_CONNECTED
error is received.
Note Nonblocking mode is supported for compatibility with Microsoft LAN Manager version 2.0, and it should not be used to achieve asynchronous input and output (I/O) with named pipes.
因此,要正确使用 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()
阻塞,请改用 Overlapped I/O。 MSDN 提供了这样的示例:
我有一段代表简单管道服务器的代码。当我设置 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
0x00000001Nonblocking mode is enabled. In this mode,
ReadFile
,WriteFile
, andConnectNamedPipe
always return immediately.
根据 ConnectNamedPipe()
文档:
If the specified pipe handle is in nonblocking mode,
ConnectNamedPipe
always returns immediately. In nonblocking mode,ConnectNamedPipe
returns a nonzero value the first time it is called for a pipe instance that is disconnected from a previous client. This indicates that the pipe is now available to be connected to a new client process. In all other situations when the pipe handle is in nonblocking mode,ConnectNamedPipe
returns zero. In these situations,GetLastError
returnsERROR_PIPE_LISTENING
if no client is connected,ERROR_PIPE_CONNECTED
if a client is connected, andERROR_NO_DATA
if a previous client has closed its pipe handle but the server has not disconnected. Note that a good connection between client and server exists only after theERROR_PIPE_CONNECTED
error is received.Note Nonblocking mode is supported for compatibility with Microsoft LAN Manager version 2.0, and it should not be used to achieve asynchronous input and output (I/O) with named pipes.
因此,要正确使用 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()
阻塞,请改用 Overlapped I/O。 MSDN 提供了这样的示例: