简体   繁体   English

跟进:Boost序列化自定义C ++对象通过ZeroMQ pull socket传递

[英]Follow up: Boost serialized custom C++ object passed over ZeroMQ pull socket

This is a follow up problem that I opened up earlier in another thread at Boost: De-serializing a custom C++ object passed over ZeroMQ pull socket . 这是我之前在Boost的另一个线程中打开的一个后续问题:反序列化通过ZeroMQ pull socket传递的自定义C ++对象 The problem in that thread has been resolved based on the answer provided. 该线程中的问题已根据提供的答案得到解决。 Now I have another problem at runtime. 现在我在运行时遇到了另一个问题。 Please, see the below description. 请参阅以下说明。 I am realtively new to C++ realm so I appreciate if you tell me any necessity for improvement in any part of the code provided in addition to what I descibed under problem statment. 我是C ++领域的新手,所以如果你告诉我除了我在问题陈述下所描述的代码之外提供的代码的任何部分,我还要感谢。

Description: 描述:

I have a C++ class named GenericMessage which simply holds an id and data as its members (See code snippet 2 below - GenericMessage.hxx). 我有一个名为GenericMessage的C ++类, 它只包含一个id和data作为其成员(参见下面的代码片段2 - GenericMessage.hxx)。 My intention is to serialize an instance of this class and send it via a ZeroMQ socket which implements the push pattern. 我的目的是序列化这个类的一个实例,并通过一个实现推送模式的ZeroMQ套接字发送它。

The serialization and sending task has been implemented in class ZMQHandler (see sendToBE function) which is placed in a header file name ZMQHandler.hxx shown in the code snippet 3 below. 序列化和发送任务已在类ZMQHandler中实现(请参阅sendToBE函数),该函数放在头文件名ZMQHandler.hxx中,如下面的代码片段3所示。 This class is instantiated by TestFE.cxx shown in the 4rd code snippet below. 此类由TestFE.cxx实例化,如下面的第4个代码片段所示。

The receiving and de-serialization of the GenericMessage instance is implemented in TestBE.cxx available in the 5th code snippet below. GenericMessage实例的接收和反序列化在TestBE.cxx中实现,可在下面的第5个代码片段中找到。 My intention is to receive the GenericMessage instance over the ZMQ socket (ie pull socket), de-serialize it and then print its members to standard output. 我的目的是通过ZMQ套接字(即拉套接字)接收GenericMessage实例,对其进行反序列化,然后将其成员打印到标准输出。

I verified that seriazalition and the GenericMessage object that is transferred over the ZeroMQ socket works fine. 我验证了通过ZeroMQ套接字传输的seriazalition和GenericMessage对象可以正常工作。 Deserialization seems to work as well cause I dont get any exception or segmentation fault like thing. 反序列化似乎也起作用,因为我没有得到任何异常或分段错误之类的东西。

Problem Statement: 问题陈述:

What is expected from the code in TestBE.cxx (see code snippet 5) is to receive the GenericMessage object over the ZeroMQ socket deserialize it and then print its two members namely id and data which is a string object in this case. TestBE.cxx中的代码(参见代码片段5)所期望的是通过ZeroMQ套接字接收GenericMessage对象反序列化它,然后打印它的两个成员,即id和数据,在这种情况下是一个字符串对象。 More precisely it should first print the content of the char stream it gets and then the members of the de-serialized object. 更确切地说,它应首先打印它获取的char流的内容,然后打印反序列化对象的成员。 Instead, it does not print these members at all. 相反,它根本不打印这些成员。 Al, it puts weird symbols including question marks into the received char stream. Al,它将包括问号在内的奇怪符号放入收到的char流中。 Please see the 1st code snippet below, you'll see my point. 请参阅下面的第一个代码段,你会看到我的观点。

QUESTIONs: 问题:

i) Why cannot I get the expected output? i)为什么我不能得到预期的输出? Why do I see the question marked weird symbols in the output? 为什么我在输出中看到标记为奇怪符号的问题? Why I don't see the id and data fields printed although they are visible in the printed char stream? 为什么我看不到打印的id和数据字段,尽管它们在打印的字符流中可见?

ii) The data field in the GenericMessage class is a template type which is set to std::string for testing purposes. ii) GenericMessage类中的数据字段是一种模板类型,为了测试目的,它被设置为std :: string。 However, in real use, I plan to transfer a much more complex object in a serialized form. 但是,在实际使用中,我计划以序列化形式传输更复杂的对象。 In this respect, do you think the use of classes boost::archive::text_iarchive and boost::archive::text_oarchive is useful. 在这方面,你认为使用类boost :: archive :: text_iarchive和boost :: archive :: text_oarchive是有用的。 Should I use binary instead? 我应该使用二进制代码吗? If so, is there some pitfalls/possible problems that you think I should be aware of? 如果是这样,您认为我应该注意一些陷阱/可能存在的问题吗? Thanks in advance. 提前致谢。

SNIPPET 1: Program output vs. expected output 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: 

CODE SNIPPET 2 (GenericMessage.hxx) 代码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;
    }

   };

CODE SNIPPET 3 (ZmqHandler.hxx) 代码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;         
     };

CODE SNIPPET 4 (TestFE.cxx) CODE 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;
        }

CODE SNIPPET 5 (TestBE.cxx) 代码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;
         }

When I build and run your code on my system, TestBE does throw the deserialization exception (every time). 当我在我的系统上构建并运行代码时, TestBE会抛出反序列化异常(每次)。 Here's what I did to fix it: 这是我做的修复它:

In your ZmqHandler class, change the method void sendToBE(GenericMessage<A> *theMsg) to void sendToBE(GenericMessage<A> theMsg) . ZmqHandler类中,将方法void sendToBE(GenericMessage<A> *theMsg)更改为void sendToBE(GenericMessage<A> theMsg) You can use a const& if you want, but you probably don't want to use a pointer here. 如果需要,可以使用const& ,但是你可能不想在这里使用指针。 In the same method, you need to change theMsg->XXX to theMsg.XXX , since theMsg is no longer a pointer. 在同一方法中,您需要将theMsg->XXX更改为theMsg.XXX ,因为theMsg不再是指针。

In TestFE , zmqHandler.sendToBE(&msg); TestFEzmqHandler.sendToBE(&msg); becomes zmqHandler.sendToBE(msg); 变成zmqHandler.sendToBE(msg); .

If theMsg must be a pointer 如果theMsg必须是指针

In ZmqHandler , just change the line archive << theMsg to archive << *theMsg . ZmqHandler ,只需将行archive << theMsgarchive << *theMsg That way, the archive's operator<< is working with the object, rather than a pointer to the object. 这样,存档的operator<<正在处理对象,而不是指向对象的指针。 The rest of your code can remain the same. 其余代码可以保持不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 增强:反序列化通过ZeroMQ拉套接字传递的自定义C ++对象 - Boost: De-serializing a custom C++ object passed over ZeroMQ pull socket 提升:序列化/反序列化通过ZeroMQ拉套接字传递的自定义C ++对象 - Boost: Serializing/De-serializing a custom C++ object passed over ZeroMQ pull socket ZeroMQ pub-sub 套接字使用 cap'n proto (C++) 接收序列化消息 object 的错误 - ZeroMQ pub-sub socket receiving error of a serialized message object using cap'n proto (C++) 尝试通过 ZeroMQ 发布-订阅套接字 (C++) 发送和接收序列化 object 时出现 Cap'n Proto 未对齐数据错误 - Cap'n Proto unaligned data error while trying to send&receive serialized object over ZeroMQ pub-sub socket (C++) C++ boost库反序列化 object 传过来 TCP 服务器 - C++ boost library deSerialize object passed over TCP server 使用C ++中的zeromq将序列化的Mat对象发送到另一台计算机 - Sending serialized Mat object to another computer using zeromq in C++ 通过ZeroMQ发送Protobuf C ++序列化字符串并使用python进行解析 - Sending a protobuf C++ serialized string over ZeroMQ and parsing using python 使用zeroMQ或boost.asio的C ++数据包嗅探器 - C++ Packet-Sniffer using zeroMQ or boost.asio 使用 boost 序列化通过 boost-asio 套接字连接发送序列化类型 - sending a serialized type over a boost-asio socket connection using boost serialization 通过套接字将Mat对象从C ++发送到Java - Sending a Mat object over socket from c++ to Java
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM