Последующие действия: Повышение качества сериализованного пользовательского объекта C ++, передаваемого через ZeroMQ

Это дополнительная проблема, которую я открыл ранее в другой теме на Ускорение: десериализация пользовательского объекта C ++, переданного через вытяжной сокет ZeroMQ. Проблема в этой теме была решена на основе предоставленного ответа. Теперь у меня есть другая проблема во время выполнения. Пожалуйста, смотрите описание ниже. Я действительно новичок в области C ++, поэтому я буду признателен, если вы сообщите мне о необходимости улучшения в любой части кода, предоставляемой в дополнение к тому, что я описал в разделе «Проблема».

Описание:

У меня есть класс C ++ с именем GenericMessage который просто содержит идентификатор и данные в качестве своих членов (см. фрагмент кода 2 ниже — GenericMessage.hxx). Мое намерение состоит в том, чтобы сериализовать экземпляр этого класса и отправить его через сокет ZeroMQ, который реализует шаблон push.

Задача сериализации и отправки была реализована в класс ZMQHandler (см. функцию sendToBE), которая находится в заголовочном файле с именем ZMQHandler.hxx, показанном в фрагмент кода 3 ниже. Этот класс создан TestFE.cxx Показано в 4-й фрагмент кода ниже.

Получение и десериализация экземпляра GenericMessage реализована в TestBE.cxx доступны в 5-й фрагмент кода ниже. Мое намерение состоит в том, чтобы получить экземпляр GenericMessage через сокет ZMQ (т. Е. Вытащить сокет), десериализовать его, а затем распечатать его элементы в стандартный вывод.

Я проверил, что seriazalition и объект GenericMessage, которые передаются через сокет ZeroMQ, работают нормально. Десериализация, кажется, тоже работает, потому что я не получаю никаких исключений или ошибок сегментации.

Постановка задачи:

Что ожидается от кода в TestBE.cxx (см. Фрагмент кода 5), так это получить объект GenericMessage через сокет ZeroMQ, десериализовать его и затем распечатать два его члена, а именно id и данные, которые в данном случае являются строковыми объектами. Точнее, он должен сначала распечатать содержимое получаемого потока символов, а затем членов десериализованного объекта. Вместо этого он вообще не печатает эти элементы. Ал, он помещает странные символы, включая знаки вопроса, в полученный поток символов. Пожалуйста, посмотрите 1-й фрагмент кода ниже, вы поймете мою точку зрения.

Вопросы:

я) Почему я не могу получить ожидаемый результат? Почему я вижу вопрос, отмеченный странными символами в выводе? Почему я не вижу напечатанных полей id и data, хотя они видны в потоке напечатанных символов?

II) Поле данных в классе GenericMessage является типом шаблона, для тестирования которого установлено значение std :: string. Однако в реальном использовании я планирую перевести намного более сложный объект в сериализованную форму. В этом отношении вы считаете полезным использование классов boost :: archive :: text_iarchive и boost :: archive :: text_oarchive. Должен ли я использовать бинарный вместо? Если да, то есть ли какие-то подводные камни / возможные проблемы, о которых, как вы думаете, я должен знать? Заранее спасибо.

SNIPPET 1: выход программы против ожидаемого результата

  *******************
The EXPECTED OUTPUT
*******************
Connecting to FE...
CHAR [22 serialization::archive 9 0 1 0
0 1 12 Hello there!]
ID: 1
Data: Hello there!

CHAR [22 serialization::archive 9 0 1 0
0 2 12 Hello there!]
ID: 2
Data: Hello there!

CHAR [22 serialization::archive 9 0 1 0
0 3 12 Hello there!]
ID: 3
Data: Hello there!

......*************************
PRINTED OUTPUT IN REALITY
*************************
Connecting to FE...
CHAR [22 serialization::archive 9 0 1 0
0 1 12 Hello there!]
ID: 1
Data: Hello there!

//continues in increasing order same as above until the 18th message in the following
CHAR [22 serialization::archive 9 0 1 0
0 18 12 Hello there!]
ID: 0
Data:

//!!!!AFTER the 18th message I got question marks in the printed char stream!!!!!
CHAR [22 serialization::archive 9 0 1 0
0 19 12 Hello there!���]
ID: 0
Data:

CHAR [22 serialization::archive 9 0 1 0
0 20 12 Hello there!���]
ID: 0
Data:

КОД SNIPPET 2 (GenericMessage.hxx)

  #include <iostream>
#include <string>
#include <sstream>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

template <class T>
class GenericMessage {
public:
GenericMessage():
beId(-1)
{}

GenericMessage(int id, T msg):
beId(id),
data(msg)
{}

~GenericMessage(){}

T getData()
{
return data;
}std::string toString()
{
std::ostringstream ss;
ss << getBeId();
std::string ret =  ss.str();

return ("ID: " + ret + " DATA: " + getData());
}

void setBeId(int id)
{
beId = id;
}

int getBeId()
{
return beId;
}private:
friend class boost::serialization::access;

int beId;
T data;template <class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & beId;
ar & data;
}

};

КОД SNIPPET 3 (ZmqHandler.hxx)

   #include "zmq.hpp"#include "GenericMessage.hxx"#include <unistd.h>
#include <cassert>

template <class A>
class ZmqHandler {
public:

ZmqHandler():
mContext(1),
mOutbHandlerSocket(mContext, ZMQ_PUSH)
{
mOutbHandlerSocket.bind ("tcp://*:5555");
}~ZmqHandler() {}

void sendToBE(GenericMessage<A> *theMsg)
{
std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);

try
{
archive << theMsg;
} catch (boost::archive::archive_exception& ex) {
std::cout << "Archive Exception during deserializing:" << std::endl;
std::cout << ex.what() << std::endl;
} catch (int e) {
std::cout << "EXCEPTION " << e << std::endl;
}

std::string outbound_data_ = archive_stream.str();
// no need to use the c-style string function 'strlen'
int len = outbound_data_.length();

zmq::message_t msgToSend(len);
memcpy( msgToSend.data(), outbound_data_.data(), len );

mOutbHandlerSocket.send(msgToSend);
std::cout << "SENT request: [" << theMsg->toString() << "]" << std::endl;
std::cout << "LENGTH [" << len << "]" << std::endl;
}

private:
zmq::context_t mContext;
zmq::socket_t mOutbHandlerSocket;
};

КОД SNIPPET 4 (TestFE.cxx)

       #include "ZmqHandler.hxx"
int main ()
{
ZmqHandler<std::string> zmqHandler;
int counter = 1;

while(1)
{
std::string data = "Hello there!";
GenericMessage<std::string> msg(counter, data);
zmqHandler.sendToBE(&msg);
counter++;
sleep(1);
}

return 0;
}

КОД SNIPPET 5 (TestBE.cxx)

       #include "zmq.hpp"#include "GenericMessage.hxx"#include <fstream>

int main ()
{
//  Prepare our context and socket
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_PULL);

std::cout << "Connecting to FE..." << std::endl;
socket.connect ("tcp://localhost:5555");

while(1){
zmq::message_t reply;
socket.recv (&reply);

const char *buf = static_cast<const char*>(reply.data());
std::cout << "CHAR [" << buf << "]" << std::endl;

std::string input_data_( buf, reply.size() );
std::istringstream archive_stream(input_data_);
boost::archive::text_iarchive archive(archive_stream);
GenericMessage<std::string> theMsg;

try
{
archive >> theMsg;
} catch (boost::archive::archive_exception& ex) {
std::cout << "Archive Exception during deserializing:" << std::endl;
std::cout << ex.what() << std::endl;
} catch (int e) {
std::cout << "EXCEPTION " << e << std::endl;
}

std::cout << "ID: " << theMsg.getBeId() << std::endl;
std::cout << "Data: " << theMsg.getData() << std::endl;

}

return 0;
}

5

Решение

Когда я собираю и запускаю ваш код в моей системе, TestBE выдает исключение десериализации (каждый раз). Вот что я сделал, чтобы это исправить:

В вашем ZmqHandler класс, смени метод void sendToBE(GenericMessage<A> *theMsg) в void sendToBE(GenericMessage<A> theMsg), Вы можете использовать const& если вы хотите, но вы, вероятно, не хотите использовать указатель здесь. В том же методе вам нужно изменить theMsg->XXX в theMsg.XXX, поскольку theMsg больше не указатель

В TestFE, zmqHandler.sendToBE(&msg); становится zmqHandler.sendToBE(msg);,

Если theMsg должен быть указателем

В ZmqHandlerпросто измените строку archive << theMsg в archive << *theMsg, Таким образом, архив operator<< работает с объектом, а не указателем на объект. Остальная часть вашего кода может остаться прежней.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]