PIPE_NOWAIT打破了连接

时间:2017-02-15 12:09:34

标签: c++ winapi pipe named-pipes

我有一段代表简单管道服务器的代码。当我设置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
    }
}

1 个答案:

答案 0 :(得分:0)

根据CreateNamedPipe()文档:

  

PIPE_NOWAIT
  0x00000001

     

启用非阻止模式。在此模式下,ReadFileWriteFile 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提供了以下示例:

Named Pipe Server Using Overlapped I/O

Named Pipe Server Using Completion Routines