写入

时间:2019-04-01 11:51:56

标签: windows pipe ipc duplex

我正在尝试使用一个NamedPipe进行双向IPC。在我看来(我无法在MSDN上找到更多信息),一个全双工管道就足够了。这是我的代码。

//Compiled with these commands during my test:
//g++ -DCLIENT -o client.exe xxx.cpp
//g++ -DSERVER -o server.exe xxx.cpp

#include <iostream>
#include <windows.h>
using namespace std;

DWORD WINAPI ReadingThread(LPVOID a)
{
    HANDLE pipe = (HANDLE)a;
    BOOL result;
    char buffer[256];
    DWORD numBytesRead;
    while (true)
    {
        result = ReadFile(pipe, buffer, sizeof(buffer) - 1, &numBytesRead, NULL);

        if (result)
        {
            buffer[numBytesRead] = 0;
            cout << "[Thread] Number of bytes read: " << numBytesRead << endl;
            cout << "[Thread] Message: " << endl
                 << buffer << endl
                 << endl;
        }
        else
        {
            cout << "[Thread] Failed to read data from the pipe. err=" << GetLastError() << endl;
            break;
        }
    }
    return 0;
}

int main(int argc, const char **argv)
{
#ifdef CLIENT
    cout << "[Main] Connecting to pipe..." << endl;
    HANDLE pipe = CreateFileA("\\\\.\\pipe\\PipeTest", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#else
    cout << "[Main] Creating an instance of a named pipe..." << endl;
    HANDLE pipe = CreateNamedPipeA("\\\\.\\pipe\\PipeTest", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, 1, 0, 0, 0, NULL);
#endif

    if (pipe == NULL || pipe == INVALID_HANDLE_VALUE)
    {
        cout << "[Main] Failed to acquire pipe handle." << endl;
        return 1;
    }

#ifdef CLIENT
#else
    cout << "[Server] Waiting for a client to connect to the pipe..." << endl;

    BOOL result = ConnectNamedPipe(pipe, NULL);
    if (!result)
    {
        cout << "[Server] Failed to make connection on named pipe." << endl;
        CloseHandle(pipe);
        return 1;
    }
    cout << "[Server] Client is here!" << endl;
    {
        const char *buf = "Hello pipe!\n";
        WriteFile(pipe, buf, strnlen(buf, 30), 0, 0);
    }
#endif

    CreateThread(0, 0, ReadingThread, pipe, 0, 0);
    cout << "[Main] Ready to send data." << endl;

    while (true)
    {
        char buffer[128];
        DWORD numBytesWritten = 0;
        BOOL result;

        cin >> buffer;
        if (!strcmp(buffer, "q"))
        {
            break;
        }
        cout << "[Main] Writing data to pipe..." << endl;
        result = WriteFile(pipe, buffer, strnlen(buffer, _countof(buffer)), &numBytesWritten, 0);
        if (result)
        {
            cout << "[Main] Written " << numBytesWritten << " bytes to the pipe." << endl;
        }
        else
        {
            cout << "[Main] Failed to write data to the pipe. err=" << GetLastError() << endl;
        }
    }
    CloseHandle(pipe);
    cout << "[Main] Done." << endl;
    return 0;
}

我可以得到“ Hello Pipe!”从服务器端到客户端的消息。我希望在任一程序的终端上键入一些字符串,然后按Enter键,然后在另一侧查看它。

但是,在问候消息之后,两个程序都将停留在WriteFile调用上。同时,线程被卡在ReadFile调用中。我如何使它工作,或者我遗漏了一些东西?

2 个答案:

答案 0 :(得分:1)

为同步I / O创建文件时(FILE_OBJECT中存在标记 geojsonData = L.geoJson(data, { style: { pmIgnore: true, weight: 20 }, }) 所有文件的I / O操作已被序列化-新操作将在I / O管理器中等待,然后再传递给驱动程序,直到当前(如果存在)未完成。在并发中只能执行单个I / O请求。如果我们确实阻止了专用线程中的读取-该文件上的所有其他I / O请求将被阻止,直到读取未完成。这不仅与写作有关。甚至查询文件名/属性也会在此处阻止。结果渲染渲染单独读取并没有帮助-我们在第一次写入尝试时会阻塞。这里的解决方案使用异步文件-这允许任何数量的I / O操作并发执行。

答案 1 :(得分:0)

Windows中的命名管道为HALF DUPLEX。如Windows 10所示。MSDN文档是错误的。已向Microsoft提交了更正其文档的请求。

虽然可以在客户端上将管道打开为“常规读取|常规写入”,但是您不能同时执行两个操作。

在第一个重叠的IO之后提交的重叠的IO将中断管道。

您可以提交重叠的io。然后等待它完成。然后提交下一个重叠的io。您不能同时提交重叠的读取和重叠的写入。

根据定义,这是“半双工”。