通过命名管道发送数据结构

时间:2015-03-09 00:19:23

标签: c++ ipc named-pipes

我发现了这个StackOverflow问题:

  
    

Create Named Pipe C++ Windows

  

创建了这个类:

#pragma once

#define PIPE_FD TEXT("\\\\.\\pipe\\somepipe")

#define BUFFER_SIZE 1024

// CPipe Class
class CPipe
{

private:

    //
    // Variables
    //

    HANDLE hPipe;
    char buffer[BUFFER_SIZE];
    DWORD dwRead;
    DWORD dwWritten;

public:

    bool CreatePipe()
    {
        hPipe = CreateNamedPipe(PIPE_FD, PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, PIPE_WAIT, 1, BUFFER_SIZE * 16, BUFFER_SIZE * 16, NMPWAIT_USE_DEFAULT_WAIT, NULL);

        return (hPipe == NULL) ? false : true;
    }

    bool CreatePipeFile()
    {
        hPipe = CreateFile(PIPE_FD, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

        return (hPipe == NULL) ? false : true;
    }

    void Destroy()
    {
        DisconnectNamedPipe(hPipe);
    }

    bool IsPipe()
    {
        return (hPipe == NULL) ? false : true;
    }

    bool IsConnected()
    {
        return (ConnectNamedPipe(hPipe, NULL) != FALSE) ? true : false;
    }

    void Read()
    {
        while (ReadFile(hPipe, buffer, sizeof(buffer), &dwRead, NULL) != FALSE)
        {
            /* do something with data in buffer */
            printf("%s", buffer);
        }
    }

    void Write()
    {
        WriteFile(hPipe, "Hello Pipe\n", 12, &dwWritten, NULL);

        CloseHandle(hPipe);
    }
};

extern CPipe gPipe;

主要流程:

    gPipe.CreatePipe();
    while (gPipe.IsPipe())
    {
        if (gPipe.IsConnected())
        {
            gPipe.Read();
        }

        gPipe.Destroy();
    }

远程:

    gPipe.CreatePipeFile();
    if (gPipe.IsPipe())
    {
        gPipe.Write();
    }

哪个效果很好。我可以在两个应用程序之间发送“Hello Pipe \ n”。但是,我试图修改它以发送数据结构而不是字符串。

例如,这个结构:

struct Test_t
{
    int x;
    int y;
    float J[3];
    bool Yes;
};

这样,客户端可以通过管道发送结构,服务器可以从管道读取结构并相应地更新本地服务器结构。

我试过了:

  
    

reinterpret_cast<char*>(&test);

  

但我无法让它发挥作用。有什么想法吗?

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

重新解释演员应该看起来像这样:

reinterpret_cast<void*>(&test);

您还需要确保获得正确传输的数据量(sizeof是您的朋友)。

请注意,发送这样的结构可能会有风险。

  • 发送的对象必须是普通的旧数据对象,否则它们将无法正确序列化。有关普通旧数据的更多信息,请参阅What are POD types in C++?。指针成员,虚拟功能等不起作用。
  • 如果相互交谈的两个过程对结构包装有不同的看法,那么另一方面就会出错。只要您完全控制构建环境,这应该没问题,但是当事情开始破坏时,您可以获得一些非常难以解决的错误。

除非你有极端的性能考虑因素,否则你应该研究一些更有条理的方法来序列化你通过管道发送的数据,例如谷歌协议缓冲区或boost :: serialize,这将确保线路格式不那么脆弱。协议缓冲区(以及许多其他技术)具有不具备c ++特性的优势,因此您可以在使用不同编程语言创建的进程之间进行通信。