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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2640642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:11:22  来源:igfitidea点击:

C++: Implementing Named Pipes using the Win32 API

c++windowswinapinamed-pipes

提问by Mike Pateras

I'm trying to implement named pipes in C++, but either my reader isn't reading anything, or my writer isn't writing anything (or both). Here's my reader:

我正在尝试在 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";
}

And here's my writer:

这是我的作家:

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";
}

Does that look right? numRead in the reader is always 0, for some reason, and it reads nothing but 1024 -54's (some weird I character).

看起来对吗?出于某种原因,阅读器中的 numRead 始终为 0,它只读取 1024 -54(一些奇怪的 I 字符)。

Solution:

解决方案:

Reader (Server):

读者(服务器):

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);
}

Writer (client):

作家(客户):

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;

The server blocks until it gets a connected client, reads what the client writes, and then sets itself up for a new connection, ad infinitum. Thanks for the help, all!

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

采纳答案by Anton Tykhyy

You must use CreateNamedPipe()to create the server end of a named pipe. Be sure to specify a non-zero buffer size, zero (documented by MSDN as 'use system default buffer size') doesn't work. MSDN has decent samplesfor a multi-threaded client&server.

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

回答by Jerry Coffin

A named pipe client can open the named pipe with CreateFile-- but the named pipe server needs to use CreateNamedPipeto create the named pipe. After it's created the named pipe, the server uses ConnectNamedPipeto wait for a client to connect. Only afterthe client has connected should the server do a blocking read like your call to ReadFile.

命名管道客户端可以使用CreateFile--打开命名管道,但命名管道服务器需要使用它CreateNamedPipe来创建命名管道。创建命名管道后,服务器用于ConnectNamedPipe等待客户端连接。只有客户端连接,服务器才应该像您调用ReadFile.