web-dev-qa-db-ja.com

C ++:Win32APIを使用した名前付きパイプの実装

名前付きパイプを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;

サーバーは、接続されたクライアントを取得するまでブロックし、クライアントが書き込んだ内容を読み取り、新しい接続のために無限にセットアップします。助けてくれてありがとう、みんな!

19
Mike Pateras

名前付きパイプのサーバー側を作成するには、 CreateNamedPipe() を使用する必要があります。必ずゼロ以外のバッファサイズを指定してください。ゼロ(MSDNによって「システムのデフォルトのバッファサイズを使用する」として文書化されています)は機能しません。 MSDNには まともなサンプル マルチスレッドクライアント&サーバー用があります。

13
Anton Tykhyy

名前付きパイプクライアントはCreateFileで名前付きパイプを開くことができますが、名前付きパイプサーバーはCreateNamedPipeを使用して名前付きパイプを作成する必要があります。名前付きパイプが作成された後、サーバーはConnectNamedPipeを使用してクライアントが接続するのを待ちます。サーバーがReadFileの呼び出しのようにブロッキング読み取りを実行する必要があるのは、afterのみです。

13
Jerry Coffin