C++:使用Win32 API实现命名管道

Mik*_*ras 18 c++ windows winapi named-pipes

我正在尝试用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";
}
Run Code Online (Sandbox Code Playgroud)

这是我的作家:

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";
}
Run Code Online (Sandbox Code Playgroud)

那看起来不错吗?由于某种原因,阅读器中的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);
}
Run Code Online (Sandbox Code Playgroud)

作家(客户):

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;
Run Code Online (Sandbox Code Playgroud)

服务器阻塞,直到它获得连接的客户端,读取客户端写入的内容,然后无限制地为自己设置新连接.谢谢大家的帮助!

Ant*_*hyy 13

您必须使用CreateNamedPipe()创建命名管道的服务器端.请务必指定非零缓冲区大小,零(由MSDN记录为"使用系统默认缓冲区大小")不起作用.MSDN 为多线程客户端和服务器提供了不错的示例.


Jer*_*fin 13

命名管道客户端可以使用CreateFile- 打开命名管道,但命名管道服务器需要CreateNamedPipe用于创建命名管道.在创建命名管道后,服务器使用ConnectNamedPipe等待客户端连接.只有客户端连接,服务器才会执行阻塞读取,就像您的呼叫一样ReadFile.