如何通过 fifo 将 protobuf 的 SerializeToOstream 和 ParseFromIstream 用于 IPC?

How to use protobuf's SerializeToOstream and ParseFromIstream for IPC via fifo?

我有客户端通过 linux fifo 将由 protobuf 序列化的消息发送到服务器。我在我的代码中使用 ifstream 和 ofstream 进行 I/O 操作。

如果我这样写:

//client
Client::request() {
  std::ofstream pipeOut;
  pipeOut.open(outputPipeName);
  msg.SerializeToOstream(&pipeOut);
  pipeOut.close();
  ...
}

//server
Server::process_requests() {
  std::ifstream pipeIn;

  while(isRunning) {
    pipeIn.open(inputPipeName);
    msg.ParseFromIstream(&pipeIn);
    pipeIn.close();
    ...
  }

}

一切正常。但我不想不断打开和关闭流。相反,我想写这样的东西:

//client
class Client {
  std::ofstream pipeOut;
};

Client::Client() {
  pipeOut.open(outputPipeName);
}

Client::~Client() {
  pipeOut.close();
}


Client::request() {
  msg.SerializeToOstream(&pipeOut);
  ...
}

//server
Server::process_requests() {
  std::ifstream pipeIn;
  pipeIn.open(inputPipeName);  

  while(isRunning) {
    msg.ParseFromIstream(&pipeIn);
    ...
  }

  pipeIn.close();
}

但是使用此代码服务器会在 ParseFromIstream 函数内阻塞,并且程序的执行不会继续进行。谁能告诉我如何正确写这个?

尝试通过 ostream 的 .flush() 函数在 "msg.SerializeToOstream(&pipeOut)" 之后刷新 pipeOut。关闭流会刷新它,这就是第一个代码示例起作用的原因。当您保持流打开并向其写入少于流缓冲区大小的数据时,读取端无法使用数据 unless/until 将写入更多数据以填充缓冲区并提示将其发送或刷新操作完成。

事实证明,问题是我使用了错误的序列化方法,protobuff 不知道消息何时结束,等待消息的下一部分,直到管道关闭。这就是代码的第一个版本有效而​​第二个版本无效的原因。我设法使用 Delimiting Protobuf Messages.

修复了此行为