Синхронизация чтения и записи с синхронными именованными трубами - PullRequest
1 голос
/ 09 февраля 2009

Сервер именованных каналов создается с

hPipe = CreateNamedPipe( zPipePath,
                         PIPE_ACCESS_DUPLEX,
                         PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE,
                         PIPE_UNLIMITED_INSTANCES,
                         8192, 8192, NMPWAIT_USE_DEFAULT_WAIT, NULL)

Тогда мы сразу же позвоним:

ConnectNamedPipe( hPipe, BYVAL %NULL )

Который блокируется до подключения клиента.

Затем перейдем непосредственно к ReadFile (hPipe, ...

Проблема в том, что Клиенту требуется определенное количество времени для подготовки и записи всех параметров запроса fcgi. Обычно это не завершается до того, как Pipe Server выполнит свой ReadFile (). Таким образом, операция чтения файла не находит данных в канале, и процесс завершается неудачей.

Существует ли механизм, позволяющий определить, когда запись () произошла / завершилась после подключения клиента к NamedPipe?

Если бы у меня был контроль над процессом Client, я мог бы использовать обычный Mutex, но я этого не делаю, и я действительно не хочу входить в порты завершения ввода / вывода просто для решения этой проблемы!

Конечно, я могу использовать простой таймер для ожидания 60 м / с или около того, что обычно достаточно для завершения записи, но это ужасный хак.

1 Ответ

4 голосов
/ 09 февраля 2009

Я не уверен, какой язык вы используете - я не распознаю выражение типа

PIPE_TYPE_BYTE OR %PIPE_WAIT OR %PIPE_READMODE_BYTE

но мне кажется, что ReadFile () сервера должен блокироваться, пока данные не будут записаны клиентом.

Одной вещью, которая выглядит неправильно (но не должна причинять вреда), является использование NMPWAIT_USE_DEFAULT_WAIT - это значение предназначено для использования клиентом при вызове WaitNamedPipe().

Не могли бы вы увидеть, взаимодействуют ли эти 2 программы на С ++ так, как вы ожидаете (т.е. с блокировкой сервера, пока клиент не что-то напишет)? Я взял эти программы из книги Джонса / Олунда «Сетевое программирование для Windows». Серверные блоки в вызове ReadFile() для меня, как и ожидалось:

- server.cpp

// Server.cpp

#include <windows.h>
#include <stdio.h>

void main(void)
{
    HANDLE PipeHandle;
    DWORD BytesRead;
    CHAR buffer[256];
    if ((PipeHandle = CreateNamedPipe("\\\\.\\Pipe\\Jim",
        PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1,
        0, 0, 1000, NULL)) == INVALID_HANDLE_VALUE)
    {
        printf("CreateNamedPipe failed with error %d\n",
            GetLastError());
        return;
    }

    printf("Server is now running\n");

    if (ConnectNamedPipe(PipeHandle, NULL) == 0)
    {
        printf("ConnectNamedPipe failed with error %d\n",
            GetLastError());
        CloseHandle(PipeHandle);
        return;
    }

    if (ReadFile(PipeHandle, buffer, sizeof(buffer),
        &BytesRead,  NULL) <= 0)
    {
        printf("ReadFile failed with error %d\n", GetLastError());
        CloseHandle(PipeHandle);
        return;
    }

    printf("%.*s\n", BytesRead, buffer);

    if (DisconnectNamedPipe(PipeHandle) == 0)
    {
        printf("DisconnectNamedPipe failed with error %d\n",
            GetLastError());
        return;
    }

    CloseHandle(PipeHandle);
}

- client.cpp

// Client.cpp

#include <windows.h>
#include <stdio.h>

#define PIPE_NAME "\\\\.\\Pipe\\jim"

void main(void)
{
    HANDLE PipeHandle;
    DWORD BytesWritten;

    if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0)
    {
        printf("WaitNamedPipe failed with error %d\n",
            GetLastError());
        return;
    }

    // Create the named pipe file handle
    if ((PipeHandle = CreateFile(PIPE_NAME,
        GENERIC_READ | GENERIC_WRITE, 0,
        (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        (HANDLE) NULL)) == INVALID_HANDLE_VALUE)
    {
        printf("CreateFile failed with error %d\n", GetLastError());
        return;
    }

    if (WriteFile(PipeHandle, "This is a test", 14, &BytesWritten, 
        NULL) == 0)
    {
        printf("WriteFile failed with error %d\n", GetLastError());
        CloseHandle(PipeHandle);
        return;
    }

    printf("Wrote %d bytes", BytesWritten);

    CloseHandle(PipeHandle);
}
...