Как использовать SerializeToOstream и ParseFromIstream protobuf для IPC через fifo?

#c #linux #stream #protocol-buffers #fifo

#c #linux #поток #буферы протокола #fifo

Вопрос:

У меня есть клиент, который отправляет сообщения, сериализованные protobuf, на сервер через linux fifo. Я использую ifstream и ofstream в своем коде для операций ввода-вывода.

Если я напишу так:

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

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

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

}
  

все работает отлично. Но я не хочу постоянно открывать и закрывать потоки. Вместо этого я хочу написать что-то вроде этого:

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

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

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


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

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

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

  pipeIn.close();
}
  

но с этим кодом сервер блокируется внутри функции ParseFromIstream, и выполнение программы прекращается. Может кто-нибудь, пожалуйста, скажите мне, как это правильно написать?

Ответ №1:

Попробуйте сбросить pipeOut после «msg.SerializeToOstream (amp;pipeOut)» с помощью функции ostream .flush(). Закрытие потока сбрасывает его, поэтому первый пример кода работает. Когда вы оставляете поток открытым и записываете в него данные меньше, чем размер буфера потока, эти данные не становятся доступными для стороны чтения, пока / пока не будет записано больше данных для заполнения буфера и запроса на его отправку ИЛИ не будет выполнена операция сброса.

Комментарии:

1. Это было первое, о чем я подумал, но нет. Я написал в ответе, в чем проблема.

Ответ №2:

Как оказалось, проблема заключалась в том, что я использовал неправильный метод для сериализации, и protobuff не знал, когда сообщение закончится, и ждал следующей части сообщения, пока канал не был закрыт. Вот почему первая версия кода работала, а вторая — нет. Мне удалось исправить это поведение, используя разделительные сообщения Protobuf.