我想将消息发送到服务器并使用命名管道读取它。当我使用WriteFile函数时,消息到达服务器,但是TransactNamedPipe失败,错误230(ERROR_BAD_PIPE),而CallNamedPipe失败,错误87(INVALID_PARAMETER)或231(PIPE_BUSY)。我已经尝试了MSDN示例,还有很多其他内容,但是仍然没有结果。请帮忙。

客户:

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <string>

#define BUFSIZE 512

int _tmain(int argc, TCHAR *argv[])
{
    OVERLAPPED ov;
    ZeroMemory(&ov, sizeof(OVERLAPPED));

    HANDLE hPipe;
    // Try to open a named pipe; wait for it, if necessary.
    while (1)
    {
        hPipe = CreateFile(
            L"\\\\.\\pipe\\PipeTest",   // pipe name
            GENERIC_READ |  // read and write access
            GENERIC_WRITE,
            0,              // no sharing
            NULL,           // default security attributes
            OPEN_EXISTING,  // opens existing pipe
            FILE_FLAG_OVERLAPPED,
            NULL);          // no template file

                            // Break if the pipe handle is valid.
        if (hPipe != INVALID_HANDLE_VALUE)
            break;

        DWORD lastErr = GetLastError();

        // Exit if an error other than ERROR_PIPE_BUSY occurs.
        if (GetLastError() != ERROR_PIPE_BUSY)
        {
            printf("Could not open pipe\n");
            return 0;
        }

        // All pipe instances are busy, so wait for 2 seconds.
        if (!WaitNamedPipe(L"\\\\.\\pipe\\PipeTest", 2000))
        {
            printf("Could not open pipe\n");
            return 0;
        }
    }

    std::wstring s;
    s.resize(1024);
    DWORD cbRead;

    BOOL fSuccess = TransactNamedPipe(
        hPipe,                  // pipe handle
        L"Hello",              // message to server
        sizeof(wchar_t) * 5, // message length
        &s[0],
        s.size() * sizeof(wchar_t),
        &cbRead,                // bytes read
        &ov);                  // not overlapped

    DWORD lastErr = GetLastError();
    GetOverlappedResult(hPipe, &ov, &cbRead, TRUE);
    DWORD lastErr2 = GetLastError();

    CloseHandle(hPipe);

    return 0;
}


服务器:

#include <iostream>
#include <string>
#include <Windows.h>

const std::wstring pipeName = L"\\\\.\\pipe\\PipeTest";

int main(void)
{
    HANDLE hPipe;
    wchar_t buffer[256];
    DWORD dwRead;

    OVERLAPPED ov;
    ZeroMemory(&ov, sizeof(OVERLAPPED));

    hPipe = CreateNamedPipe(pipeName.c_str(),
        PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,   // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
        PIPE_WAIT,
        1,
        1024 * 16,
        1024 * 16,
        NMPWAIT_USE_DEFAULT_WAIT,
        NULL);

    if (hPipe != INVALID_HANDLE_VALUE)
    {
        if (ConnectNamedPipe(hPipe, &ov) != FALSE)   // wait for someone to connect to the pipe
        {
            while (ReadFile(hPipe, buffer, 255, &dwRead, &ov) != FALSE)
            {
                WriteFile(hPipe, L"lalala", 6 * sizeof(wchar_t), &dwRead, &ov);

                DWORD lastErr1 = GetLastError();
                GetOverlappedResult(hPipe, &ov, &dwRead, TRUE);
                DWORD lastrr2 = GetLastError();

                printf("%s", buffer);
            }
        }

        DisconnectNamedPipe(hPipe);
    }

    return 0;
}

最佳答案

如果您阅读有关TransactNamedPipe


  如果服务器未将管道创建为TransactNamedPipe,则失败。
  消息类型的管道,或者管道句柄不在消息读取模式下。


CallNamedPipe


  调用CallNamedPipe等效于调用CreateFile(或
  WaitNamedPipe,如果CreateFile无法立即打开管道),
  TransactNamedPipe和CloseHandle函数


因此此功能仅适用于消息类型管道

但是,当您创建服务器管道时,请使用PIPE_TYPE_BYTE | PIPE_READMODE_BYTE
因此,CallNamedPipe和/或TransactNamedPipe必须失败。

您需要改用ReadFile / WriteFile。或使用标志PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE创建服务器并为客户端句柄调用SetNamedPipeHandleState以将其设置为消息读取模式(使用PIPE_READMODE_MESSAGE

关于c - CallNamedPipe和TransactNamedPipe不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42627347/

10-10 16:38