[zeromq-dev] How to send/receive a custom C++ object via zeromq.

Riskybiz riskybizLive at live.com
Sun Sep 29 00:05:28 CEST 2013


I've managed to fix the problem and now am able to use boost::serialization
to pass serialized data via zeromq.  I've posted the test program code below
in case it might be of use to someone else trying to do the same in
future..There is a class declaration, a server program and a client program.
The client makes a serialised request and the server sends a serialized
message in reply.

 

Thanks for help and guidance in getting this to work.

 

Riskybiz.

 

 

 

//Server

//Intended to send a serialized object instance to a client

 

#include <zmq.hpp>

#include <string>

#include <sstream>

#include <vector>

#include <boost\archive\text_iarchive.hpp>

#include <boost\archive\text_oarchive.hpp>

#include "TestClass.h"

 

int main () {

    //Prepare our context and socket

    zmq::context_t context (1);

    zmq::socket_t socket (context, ZMQ_REP);

    socket.bind ("tcp://*:4444");

 

//Create a vector with some object instances

std::vector<TestClass> testVec;

for(unsigned int i = 0; i < 10; ++i)

{

std::string idStr = static_cast<std::ostringstream*>( &(std::ostringstream()
<< std::fixed << std::setprecision(0) <<  i))->str();

TestClass obj(i, "Test Message: " + idStr);

testVec.push_back(obj);

}

 

 

 

while (true)

{

std::cout << "Server ready & waiting...." << std::endl;

 

zmq::message_t request;

        //Wait for next request from client

        socket.recv(&request);

 

//Deserialize client request

int index;                

//Cast the request data to a string

std::string reqStr( static_cast<char*>(request.data()), request.size());

        //Initialise istringstream with received serialized string data

std::istringstream ibuffer(reqStr);

//Initialise the archive

boost::archive::text_iarchive iarchive(ibuffer);

//Deserialize the archive into the variable

iarchive & index;

std::cout << "Client Requested Index: " << index << std::endl;

 

 

//Prepare the reply

std::ostringstream obuffer;

//Initialise the archive

boost::archive::text_oarchive oarchive(obuffer);

//Serialise object at requested vector index

oarchive & testVec.at(index);

//Get the serialization data (a string) from the buffer

std::string outStr(obuffer.str());

        

//Send data to client

zmq::message_t reply(outStr.size());

memcpy((void *) reply.data(), outStr.data(), outStr.size());

socket.send(reply);

std::cout << "Server Replied: " << outStr << std::endl;

     }

    return 0;

}

 

//Client

//Intended to send a request to the server and receive, then deserialize an
object

#include <zmq.hpp>

#include <string>

#include <iostream>

#include <sstream>

#include <boost\archive\text_iarchive.hpp>

#include <boost\archive\text_oarchive.hpp>

#include "TestClass.h"

 

int main ()

{

    //  Prepare our context and socket

    zmq::context_t context (1);

    zmq::socket_t socket (context, ZMQ_REQ);

 

    std::cout << "Connecting to server...." << std::endl;

    socket.connect ("tcp://localhost:4444");

 

    //  Do 10 requests, waiting each time for a response

    for (int request_nbr = 0; request_nbr != 10; request_nbr++) {

 

std::ostringstream obuffer;

boost::archive::text_oarchive oarchive(obuffer);

oarchive & request_nbr;//serialize the request

std::string reqStr(obuffer.str());//Get the serialization data (a string)
from the buffer

 

zmq::message_t request(reqStr.size());

        memcpy ((void *) request.data(), reqStr.data(), reqStr.size());


        socket.send (request);

std::cout << "Sent Request " << request_nbr << "...." << std::endl;

 

 

 

        

//Get the reply.

        zmq::message_t reply;                        

        socket.recv (&reply);

//std::cout << "Received the reply...." << std::endl;

 

TestClass obj1;

//std::cout << "Defined TestClass Object...." << std::endl;

 

std::string repStr( static_cast<char*>(reply.data()), reply.size() );//cast
received message data to a string

//std::cout << "Received Message: " << repStr << std::endl;

 

std::istringstream ibuffer(repStr);//initialise with received serialized
string data

//std::cout << "Initialised buffer...." << std::endl;

 

boost::archive::text_iarchive iarchive(ibuffer);

//std::cout << "Prepared archive...." << std::endl;

 

iarchive & obj1;//deserialise the archive into TestClass instance

//std::cout << "Deserialized...." << std::endl;

 

//Check that data members of the deserialised object may be accessed

std::cout << "Received: " << request_nbr << " ID: " << obj1.ID << " Message:
" << obj1.text << std::endl;       

    }

    return 0;

}

 

#ifndef TEST_CLASS_H

#define TEST_CLASS_H

 

//#include <string>

//#include <boost\archive\text_oarchive.hpp>

//#include <boost\archive\text_iarchive.hpp>

 

class TestClass

{

 

public:

TestClass():ID(0), text("blank")//default constructor

{

}

 

TestClass(const unsigned int id, const std::string txt):ID(id),
text(txt)//constructor

{

}

 

TestClass::TestClass(const TestClass& orig):ID(orig.ID),
text(orig.text)//copy constructor

{

}

 

~TestClass()//destructor

{

}

 

const unsigned int ID;

const std::string text;

 

private:

 

friend class boost::serialization::access;

 

template<typename Archive>

void serialize(Archive& archive, const unsigned version)

    {

     archive & const_cast<unsigned int&>(ID) &
const_cast<std::string&>(text);

    }

};//class

#endif

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20130928/0837347b/attachment.htm>


More information about the zeromq-dev mailing list