【问题标题】:C++ : Send an object through a named pipeC++:通过命名管道发送对象
【发布时间】:2016-04-15 10:28:51
【问题描述】:

我尝试通过命名管道在两个进程之间使用 ifstream 和 ofstream 在 C++ 中发送对象。我已经阅读并尝试了很多东西,但我的研究一无所获。

我在我的对象序列化期间阻塞。 当我尝试投射并发送到我的命名管道时,我无法将我的对象恢复到正常状态。

我尝试使用此代码进行操作,但对象在命名管道中通过后未满:

#include <string.h>
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

class Obj {
public:
    std::string text1;
    std::string text2;
};

int main() {

    mkfifo("fifo", 0666);

    if (fork() == 0) //Receiving Side
    {

        std::ifstream fifo("fifo", std::ofstream::binary);

        //Re-make the object
        Obj *tmp = new Obj();
        char *b = new char[sizeof(*tmp)];

        //Receive from named pipe
        fifo >> b;

        //Recover the object
        memcpy(&*tmp, b, sizeof(*tmp));

        //Display object content
        std::cout << tmp->text1 << std::endl << tmp->text2 << std::endl;

        //!\ Output = "Some \n" /!\\

        fifo.close();
        delete tmp;
        delete[] b;
    }
    else //Sending Side
    {
        std::ofstream fifo("fifo", std::ofstream::binary);

        //Create the object
        Obj *struct_data = new Obj();
        struct_data->text1 = "Some text";
        struct_data->text2 = "Some text";

        char *b = new char[sizeof(*struct_data)];

        //Serialize the object
        memcpy((void *)b, &*struct_data, sizeof(*struct_data));

        //Send to named pipe
        fifo << b;

        fifo.close();
        wait(NULL);
        delete[] b;
    }

    //delete struct_data;
    return (0);
}

有人可以给我一个提示或示例吗?

谢谢! :)

【问题讨论】:

  • 向我们展示序列化代码。是否记录了字节格式?如果是这样,请向我们展示文档。如果没有,请记录下来。相信我,记录任何协议都是值得的——最好是在编写代码之前。
  • 当你说“cast and send”时......你实际上是在序列化,还是只是试图发送原始字节?你的对象是什么样的?
  • 您的问题可能与管道(命名或未命名)无关。您可以尝试让发送者写入标准输出,而阅读者从标准输入接收对象并将它们与| 连接。节省了很多精力来设置管道等等。
  • @Bross 没有序列化对象的代码!

标签: c++ serialization casting named-pipes fifo


【解决方案1】:

您需要正确序列化您的对象。像这样(只做了一个成员,其余的将留给读者作为练习):

#include <iostream>
#include <fstream>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>

class Obj
{
  public:
    std::string text1;
    std::string text2;

  friend std::ostream& operator<<(std::ostream &os, const Obj& o);
  friend std::istream& operator>>(std::istream &os, Obj& o);
};

std::ostream& operator<<(std::ostream &os, const Obj& o)
{
  os << o.text1.length();
  os << o.text1;
  return os;
}

std::istream& operator>>(std::istream &is, Obj& o)
{
  size_t length;
  is >> length;
  char* tmp = new char[length];
  is.get(tmp, length+1); 
  o.text1 = tmp;
  delete[] tmp;
  return is;
}

static const char* myfifo = "myfifo";

int main(int argc, char *argv[])
{
  mkfifo(myfifo, 0666);

  if (argc > 1)
  {       
    std::ifstream infifo(myfifo, std::ifstream::binary);

    Obj *tmp = new Obj();

    infifo >> *tmp; 
    infifo.close();

    std::cout << "Done reading : [" << tmp->text1 << "]" << std::endl;
  }
  else
  {
    std::ofstream outfifo(myfifo, std::ofstream::binary);

    Obj *struct_data = new Obj();
    struct_data->text1 = "Some text1";
    struct_data->text2 = "Some text2";

    outfifo << *struct_data;
  }
  return 0;
}

有关序列化的更多信息,请参阅https://stackoverflow.com/a/26337239/2742863

【讨论】:

  • 一些吹毛求疵:(1)为什么operator&gt;&gt;的朋友声明是const? (2) 为什么不在operator&gt;&gt; 中返回os? (3)为什么在operator&gt;&gt;中将输入流命名为os(即输出流,IIUC的缩写)?
  • 另外,os.get(tmp, length+1); 不是一个 off-by-1 错误吗?
  • @OrenMilman,您说的完全正确,良好的命名对可读性很重要。那里有一些草率的代码,我想我现在已经修复了。我不认为存在“off-by-1”错误。根据文档 (cplusplus.com/reference/istream/istream/get),读取“直到提取 (n-1) 个字符”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
相关资源
最近更新 更多