C++ 管道断开连接

C++ 管道断开连接,c++,winapi,pipe,named-pipes,C++,Winapi,Pipe,Named Pipes,我有一段代码,它表示简单的管道服务器。当我设置PIPE_NOWAIT属性,然后尝试使用CreateFile函数从客户端连接到它时,什么都没有发生,我们仍然处于第二个块中。当我删除PIPE_NOWAIT标志时,我们挂起ConnectNamedPipe函数,从客户端调用CreateFile后,我们进入第一个块,这意味着我们成功了。为什么会这样 HANDLE hPipe; std::string msg; DWORD dwRead; hPipe = CreateNamedPipe(L"\\\\.\\

我有一段代码,它表示简单的管道服务器。当我设置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
    }
}
根据文件:

管道(无管道)
0x00000001

非阻塞模式已启用。在此模式下,
ReadFile
WriteFile
ConnectNamedPipe
始终立即返回

根据文件:

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

注意:为了与Microsoft LAN Manager 2.0版兼容,支持非阻塞模式,不应使用非阻塞模式实现命名管道的异步输入和输出(I/O)。

因此,要正确使用
PIPE\u 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\u NOWAIT
。如果不希望
ConnectNamedPipe()
阻塞,请改用重叠I/O。MSDN提供了以下示例:


为什么使用
管道\u NOWAIT
?您需要使用
FILE\u FLAG\u OVERLAPPED
为什么我不能这样做?
PIPE\u NOWAIT
-
请注意,为了与Microsoft LAN Manager 2.0版兼容,支持非阻塞模式,不应使用非阻塞模式来实现命名管道的异步I/O。
如果您想要异步I/O,请使用
FILE\u FLAG\u OVERLAPPED
,但我需要只想让ConnectNamedPipe不挂起并控制它,例如,在我想要的时候停止。在异步模式下
ConnectNamedPipe
几乎总是返回
FALSE
-这里没有问题。和
GetLastError
返回
ERROR\u IO\u PENDING
(直到没有连接),
ERROR\u PIPE\u CONNECTED
客户端已连接,
ERROR\u no\u DATA
(客户端已连接并断开连接