C ++: реализация именованных каналов с использованием Win32 API - PullRequest
18 голосов
/ 15 апреля 2010

Я пытаюсь реализовать именованные каналы в C ++, но либо мой читатель ничего не читает, либо мой писатель ничего не пишет (или оба). Вот мой читатель:

int main()
{
    HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

    char data[1024];
    DWORD numRead = 1;

    while (numRead >= 0)
    {
        ReadFile(pipe, data, 1024, &numRead, NULL);

        if (numRead > 0)
            cout << data;
    }

    return 0;
}

LPCWSTR GetPipeName()
{
    return L"\\\\.\\pipe\\LogPipe";
}

А вот мой писатель:

int main()
{
    HANDLE pipe = CreateFile(GetPipeName(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

    string message = "Hi";
    WriteFile(pipe, message.c_str(), message.length() + 1, NULL, NULL); 

    return 0;
}

LPCWSTR GetPipeName()
{
    return L"\\\\.\\pipe\\LogPipe";
}

Это выглядит правильно? По какой-то причине в считывающем устройстве numRead всегда равно 0, и он читает только 1024 -54 (какой-то странный символ I).

Решение:

Считыватель (сервер):

while (true)
{
    HANDLE pipe = CreateNamedPipe(GetPipeName(), PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);

    if (pipe == INVALID_HANDLE_VALUE)
    {
        cout << "Error: " << GetLastError();
    }

    char data[1024];
    DWORD numRead;

    ConnectNamedPipe(pipe, NULL);

    ReadFile(pipe, data, 1024, &numRead, NULL);

    if (numRead > 0)
        cout << data << endl;

    CloseHandle(pipe);
}

Автор (клиент):

HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

if (pipe == INVALID_HANDLE_VALUE)
{
    cout << "Error: " << GetLastError();
}

string message = "Hi";

cout << message.length();

DWORD numWritten;
WriteFile(pipe, message.c_str(), message.length(), &numWritten, NULL); 

return 0;

Сервер блокируется до тех пор, пока не получит подключенного клиента, не прочитает то, что пишет клиент, а затем настроит себя для нового соединения до бесконечности. Спасибо за помощь, всем!

Ответы [ 2 ]

13 голосов
/ 15 апреля 2010

Клиент именованного канала может открыть именованный канал с помощью CreateFile, но серверу именованного канала необходимо использовать CreateNamedPipe для создания именованного канала. После создания именованного канала сервер использует ConnectNamedPipe для ожидания подключения клиента. Только после , когда клиент подключился, если сервер выполняет блокировку, читаемую как ваш звонок на ReadFile.

13 голосов
/ 15 апреля 2010

Вы должны использовать CreateNamedPipe() для создания серверной части именованного канала. Обязательно укажите ненулевой размер буфера, ноль (задокументированный MSDN как «использовать размер буфера по умолчанию для системы») не работает. MSDN имеет приличных образцов для многопоточного клиента и сервера.

...