ZMQ:通过ZMQ队列发送自定义CPP对象

时间:2013-01-21 11:21:08

标签: c++ zeromq memcpy

我有一个名为GenericMessage的类,显示在下面的第一个代码片段中(在GenericMessage.hxx中定义)。

我有一个名为TestFE.cpp的.cpp文件(参见下面的第二个代码片段),它试图通过ZMQ队列发送类GenericMessage的实例(另请参阅下面的第四个代码片段 - ZmqHandler.hxx)。 TesfFE.cpp通过包含ZmqHandler.hxx来实现ZMQ推送模式。

我还有另一个名为TestBE.cpp的.cpp文件(参见下面的第三个代码片段),它通过ZMQ队列接收如此提到的GenericMessage实例。 TestBE.cpp在此实现ZMQ拉模式,以通过ZMQ队列检索GenericMessage实例。

在TestFE.cpp中,我使用标准的memcpy函数将GenericMessage对象转换为ZMQ队列可以接受的形式。在TestBE.cpp的第21行(在注释的第3个代码片段中标记),我得到了一个分段错误,因为它看起来memcpy在发送方这是TestFE.cpp时无法正常工作。 TestBE执行时,我收到以下消息。我也在下面提供gdb回溯。你能告诉我这里有什么问题吗?为什么你认为memcpy不能正确地将我的GenericMessage对象复制到ZMQ message_t格式?或者你认为这个问题还存在吗?任何意见将不胜感激。

错误消息

  $ ./TestBE
  Connecting to FE...
  RECEIVED: 1
  Segmentation fault (core dumped)

GDB Backtrace

  (gdb) r
   Starting program: /home/holb/HOLB_DESIGN/ZMQ/WORK1/TestBE 
  [Thread debugging using libthread_db enabled]
  Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
  [New Thread 0xb7c84b40 (LWP 4252)]
  [New Thread 0xb7483b40 (LWP 4253)]
  Connecting to FE...
  RECEIVED: 1

  Program received signal SIGSEGV, Segmentation fault.
  0xb7f371cc in std::basic_string<char, std::char_traits<char>, std::allocator<char>       >::basic_string(std::string const&) ()
  from /usr/lib/i386-linux-gnu/libstdc++.so.6
  (gdb) bt
  #0  0xb7f371cc in std::basic_string<char, std::char_traits<char>,      std::allocator<char> >::basic_string(std::string const&) ()
  from /usr/lib/i386-linux-gnu/libstdc++.so.6
  #1  0x08049621 in GenericMessage<std::string>::getData (this=0xbffff06c)
  at GenericMessage.hxx:18
  #2  0x08049075 in main () at TestBE.cxx:21
 (gdb) 

CODE SNIPPET 1(GenericMessage.hxx)       #包括       #包括       #include

  template <class T>
  class GenericMessage {
  public:

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

         ~GenericMessage(){}

         T getData()
         {
           //LINE 18 is the following line!
           return data;
         }

          std::string toString()
          {
              std::ostringstream ss;
              ss << getBeId();
              std::string ret =  ss.str();

              return ret;
          }

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

          int getBeId()
          {
             return beId;
          }
 private:
        int beId;
        T data;
 };

CODE SNIPPET 2(TestFE.cxx ==&gt;发件人)      #include“ZmqHandler.hxx”      //查看底部的第4个片段,了解ZmqHandler.hxx的内容

 int main ()
 {
     ZmqHandler<std::string> zmqHandler;
     int counter = 1;

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

     return 0;
 }

CODE SNIPPET 3(TestBE.cxx ==&gt;接收者)

  #include "zmq.hpp"
  #include "GenericMessage.hxx"
  #include <string>
  #include <iostream>

  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);
            GenericMessage<std::string> *msg = (GenericMessage<std::string>*)(reply.data());                
            std::cout << "RECEIVED: " << msg->toString() << std::endl;

           /* *********************************  */
           /*  SEGMENTATION FAULT HAPPENS HERE   */
           /* The member "data" in class GenericMessage cannot be received while the  member "id" in the previous line can be received. */
           std::cout << "DATA: " << ((std::string)msg->getData())  << std::endl;
           /* ********************************** */
     }

     return 0;
 }

代码SNIPPET 4(ZMQHandler.hxx)

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

  template <class T>
  class ZmqHandler {
  public:
        ZmqHandler():
    mContext(1),
    mOutbHandlerSocket(mContext, ZMQ_PUSH)
        {    
          mOutbHandlerSocket.bind ("tcp://*:5555");       
        }

       ~ZmqHandler() {}

       void *sendToBE(GenericMessage<T> *theMsg)
       {
         //  Place the new request to the zmq queue for BE consumption
         zmq::message_t msgToSend(sizeof(*theMsg));

         memcpy ( msgToSend.data(), ((GenericMessage<T>*)theMsg), sizeof(*  ((GenericMessage<T>*)theMsg)));

         mOutbHandlerSocket.send(msgToSend);

         std::cout << "SENT request: [" << theMsg->toString() << "]" << std::endl;

         return (NULL);
        }   

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

};

1 个答案:

答案 0 :(得分:4)

我开始看到问题所在。您发送完整的&#34;结构&#34;,其中包含一个具有指针的成员变量(std::string)。这是你做不到的,因为指针只在创建它们的程序中有效。

发送前必须先serialize结构,然后在接收端反序列化。

您可以使用Boost serialization等库,或Google protocol buffers或任何其他数量的库。