Named Pipe CreateFile() returns INVALID_HANDLE_VALUE, and GetLastError() returns ERROR_PIPE_BUSY

会有一股神秘感。 提交于 2019-11-30 15:00:59

From Named Pipe Client:

If the pipe exists but all of its instances are busy, CreateFile returns INVALID_HANDLE_VALUE and the GetLastError function returns ERROR_PIPE_BUSY. When this happens, the named pipe client uses the WaitNamedPipe function to wait for an instance of the named pipe to become available.

The link has example code on coping with ERROR_PIPE_BUSY.

EDIT:

Small compilable example that demonstrates accepting and connecting on a named pipe:

const char* const PIPE_NAME = "\\\\.\\pipe\\test";
const int MAX_CONNECTIONS   = 10;

void client_main()
{
    DWORD last_error;
    unsigned int elapsed_seconds       = 0;
    const unsigned int timeout_seconds = 5;

    HANDLE handle = CreateFile(PIPE_NAME,
                               GENERIC_READ | GENERIC_WRITE,
                               0,
                               0,
                               OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,
                               0);

    while (INVALID_HANDLE_VALUE == handle &&
           elapsed_seconds < timeout_seconds)
    {
        last_error = GetLastError();

        if (last_error != ERROR_PIPE_BUSY)
        {
            break;
        }

        Sleep(1 * 1000);
        elapsed_seconds++;

        handle = CreateFile(PIPE_NAME,
                            GENERIC_READ | GENERIC_WRITE,
                            0,
                            0,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            0);
    }

    if (INVALID_HANDLE_VALUE == handle)
    {
        std::cerr << "Failed to connect to pipe " << PIPE_NAME <<
            ": last_error=" << last_error << "\n";
    }
    else
    {
        std::cout << "Connected to pipe " << PIPE_NAME << "\n";
        CloseHandle(handle);
    }
}

HANDLE _get_server_handle()
{
    // Error handling omitted for security descriptor creation.
    SECURITY_DESCRIPTOR sd;
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);

    SECURITY_ATTRIBUTES sa;
    sa.nLength              = sizeof(sa);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle       = FALSE;

    // Create a bi-directional message pipe.
    HANDLE handle = CreateNamedPipe(PIPE_NAME,
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_MESSAGE       |
                                      PIPE_READMODE_MESSAGE |
                                      PIPE_NOWAIT,
                                    PIPE_UNLIMITED_INSTANCES,
                                    4096,
                                    4096,
                                    0,
                                    &sa);

    if (INVALID_HANDLE_VALUE == handle)
    {
        std::cerr << "Failed to create named pipe handle: last_error=" <<
            GetLastError() << "\n";
    }

    return handle;
}

void server_main()
{
    HANDLE handle = _get_server_handle();

    if (INVALID_HANDLE_VALUE != handle)
    {
        int count = 0;
        while (count < MAX_CONNECTIONS)
        {
            BOOL result = ConnectNamedPipe(handle, 0);

            const DWORD last_error = GetLastError();

            if (ERROR_NO_DATA == last_error)
            {
                count++;
                std::cout << "A client connected and disconnected: count=" <<
                    count << "\n";
                CloseHandle(handle);
                handle = _get_server_handle();
            }
            else if (ERROR_PIPE_CONNECTED == last_error)
            {
                count++;
                std::cout << "A client connected before call to " <<
                    "ConnectNamedPipe(): count=" << count << "\n";
                CloseHandle(handle);
                handle = _get_server_handle();
            }
            else if (ERROR_PIPE_LISTENING != last_error)
            {
                std::cerr << "Failed to wait for connection: last_error=" <<
                    GetLastError() << "\n";
                CloseHandle(handle);
                break;
            }
            Sleep(100);
        }
    }
}

int main(int a_argc, char** a_argv)
{
    if (2 == a_argc)
    {
        if (std::string("client") == *(a_argv + 1))
        {
            for (int i = 0; i < MAX_CONNECTIONS; i++)
            {
                client_main();
            }
        }
        else if (std::string("server") == *(a_argv + 1))
        {
            server_main();
        }
    }
    return 0;
}

Execute server-side first:

pipetest.exe server

Then execute client-side:

pipetest.exe client

I could not tell what the problem was from the posted code. Hopefully this small example will assist you in finding the issue.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!