C++ 跟进:Boost序列化定制C++;对象通过ZeroMQ pull套接字传递
这是一个后续问题,我在前面的另一个线程中打开了。根据提供的答案,该线程中的问题已得到解决。现在我在运行时遇到了另一个问题。请参见下面的描述。我对C++领域很有新意,所以如果你告诉我除了在问题陈述中所提出的代码之外,还需要改进代码中的任何部分。 说明: < P>我有一个C++类,名为“强>通用消息/<强”,它只将ID和数据作为成员(参见下面的代码片段2——GyrimeMeal.HXX)。我的意图是序列化这个类的一个实例,并通过实现推模式的ZeroMQ套接字发送它 序列化和发送任务已在类ZMQHandler中实现(请参阅sendToBE函数),该类位于标题文件ZMQHandler.hxx中,如下面的代码片段3所示。该类由下面的第4个代码段所示的TestFE.cxx实例化 GenericMessage实例的接收和反序列化在下面的第五个代码段中的TestBE.cxx中实现。我的目的是通过ZMQ套接字(即pull套接字)接收GenericMessage实例,对其进行反序列化,然后将其成员打印到标准输出 我验证了seriazalition和通过ZeroMQ套接字传输的GenericMessage对象工作正常。反序列化似乎也很有效,因为我并没有得到任何异常或分段错误之类的东西 问题陈述: TestBE.cxx中的代码(请参阅代码片段5)期望通过ZeroMQ套接字接收GenericMessage对象,并对其进行反序列化,然后打印其两个成员,即id和data,在本例中,这是一个字符串对象。更准确地说,它应该首先打印它获取的字符流的内容,然后打印反序列化对象的成员。相反,它根本不打印这些成员。它将奇怪的符号(包括问号)放入接收到的字符流中。请看下面的第一段代码,你会明白我的观点 问题: i)为什么我不能获得预期的输出?为什么我会在输出中看到标有奇怪符号的问题?为什么我看不到打印的id和数据字段,尽管它们在打印的字符流中是可见的 ii)GenericMessage类中的数据字段是一种模板类型,出于测试目的设置为std::string。然而,在实际使用中,我计划以序列化形式传输更复杂的对象。在这方面,您认为使用boost::archive::text\u iarchive和boost::archive::text\u iarchive类有用吗。我应该改用二进制吗?如果是,您认为我应该注意哪些陷阱/可能的问题?提前谢谢 片段1:程序输出与预期输出C++ 跟进:Boost序列化定制C++;对象通过ZeroMQ pull套接字传递,c++,boost,zeromq,boost-serialization,C++,Boost,Zeromq,Boost Serialization,这是一个后续问题,我在前面的另一个线程中打开了。根据提供的答案,该线程中的问题已得到解决。现在我在运行时遇到了另一个问题。请参见下面的描述。我对C++领域很有新意,所以如果你告诉我除了在问题陈述中所提出的代码之外,还需要改进代码中的任何部分。 说明: < P>我有一个C++类,名为“强>通用消息/XXX更改为theMsg.XXX,因为theMsg不再是指针 在TestFE中,zmqHandler.sendToBE(&msg);变成zmqHandler.sendToBE(msg); 如果msg必须
*******************
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:
代码片段2(GenericMessage.hxx)
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
模板
类泛型消息{
公众:
GenericMessage():
北纬(-1)
{}
GenericMessage(int-id,T-msg):
北斗七星,
数据(msg)
{}
~GenericMessage(){}
T getData()
{
返回数据;
}
std::string toString()
{
std::ostringstream ss;
ss当我在我的系统上构建并运行代码时,TestBE
会抛出反序列化异常(每次)。下面是我修复该异常的方法:
在ZmqHandler
类中,将方法void sendToBE(GenericMessage*theMsg)
更改为void sendToBE(GenericMessage theMsg)
。如果愿意,您可以使用常量&
,但您可能不想在此处使用指针。在相同的方法中,您需要将theMsg->XXX
更改为theMsg.XXX
,因为theMsg
不再是指针
在TestFE
中,zmqHandler.sendToBE(&msg);
变成zmqHandler.sendToBE(msg);
如果msg
必须是指针
在ZmqHandler
中,只需更改行archive,这是对ZmqHandler类的一个快速建议:如果将void sendToBE(GenericMessage*theMsg)
更改为void sendToBE(a*theMsg)
,则处理程序将适用于任何实现boost序列化接口(并与文本存档一起工作)的类当然,main
函数中的ZmqHandler-ZmqHandler;
行将变成ZmqHandlerZmqHandler;
当我定义像sendToBE(GenericMessage theMsg)或sendToBE(GenericMessage&theMsg)这样的函数时会看到,它可以正常工作。我的意思是非指针和引用类型可以正常工作。但是,如果我使用类似sendToBE(GenericMessage*theMsg)的指针定义它,那么它就不工作(我的意思是它不打印成员)。
#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;
}
};
#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;
};
#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;
}
#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;
}