Zeromq: How to access tcp message in c++
Asked Answered
G

3

17

I am a new-by to ZeroMQ and make my way through the C++ hello-world example of the echo client-server pattern (Request-Reply). The server looks like:

//
// Hello World server in C++
// Binds REP socket to tcp://*:5555
// Expects "Hello" from client, replies with "World"
//
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>

int main () {
    // Prepare our context and socket
    zmq::context_t context (1);
    zmq::socket_t socket (context, ZMQ_REP);
    socket.bind ("tcp://*:5555");

    while (true) {
        zmq::message_t request;

        // Wait for next request from client
        socket.recv (&request);
        std::cout << "Received Hello" << std::endl;

        // Do some 'work'
        sleep (1);

        // Send reply back to client
        zmq::message_t reply (5);
        memcpy ((void *) reply.data (), "World", 5);
        socket.send (reply);
    }
    return 0;
}

Now my question: How can I access / read the real data that socket.recv() ? Trying:

 std::cout << request << std::endl;

resulted in an error message:

 error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = 
 std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)
 (& std::cout)), ((const char*)"Received Hello")) << request’

The same goes for the client side that is sending the message. I don't find a way to display the real message...

Glaydsglaze answered 5/6, 2012 at 16:35 Comment(5)
I believe the ZeroMQ documentation has examples in C++. Have you looked at those?Motorize
You're right, there is an entry for zmq_msg_data that says "The zmq_msg_data() function shall return a pointer to the message content of the message object referenced by msg." But how do I do this explicitly?Glaydsglaze
No, I mean the Guide is full of C++ code examples.Motorize
I read the guide but unfortunately it doesn't include what I'm looking for...Glaydsglaze
@Iarsks have you read the guide ? If you have then you would recognize the above code as being from the guide. In there they just say "received hello" instead of actually reading the message that was sent. I've actually come here for the very same question as the OP.Rodina
M
46

The hello world example goes only half way and outputs the hard-coded values:

std::cout << "Received Hello" << std::endl;

Printing the actual response can be done as follows:

zmq::message_t reply;
socket.recv (&reply);

std::string rpl = std::string(static_cast<char*>(reply.data()), reply.size());

std::cout << rpl << std::endl;

There are some other useful examples in zhelpers.hpp.

Munos answered 10/6, 2012 at 7:35 Comment(4)
Nice first answer @NikolaiKoudelia.Moleskin
are you using c binding of zmq (cppzmq) or the zmq without any binding?Effulgent
Yes, the binding (zmq.hpp) is needed.Munos
Fantastic response. This really should be included in the Hello World example.Norwegian
G
1

I found that the following does what I want:

zmq::message_t request (msglen);
memcpy ( (void *) request.data(), myMessage, msglen);
char * requestmsg = new char [msglen];
memcpy (requestmsg, request.data(), request.size());
requestsocket.send (request);
std::cout << "Sending " <<  requestmsg << std::endl;

where msglen is of type int and myMessage is const char * tyoe. In this way, the server receives a human readable message. Hope this is not against any zeromq rules...

Glaydsglaze answered 12/6, 2012 at 12:18 Comment(1)
Since you are in C++ why not use strings ? I mean char* are just a pain unless you really need them for some obscure reasons (other libraries for example).Rodina
M
1

While I think we need to go through the guide before we can write elegant ZeroMQ codes. I found lines of simple codes from the HELLO WORLD example for extracting data received from the socket and sending back response:

    zmq::message_t request;
    socket.recv (&request);
    std::cout << "Received request: [" << (char*) request.data() << "]" << std::endl;
    //  Do some 'work'
    Sleep (1);
    //  Send reply back to client
    zmq::message_t reply (6);
    memcpy ((void *) reply.data (), "World", 6);
    socket.send (reply);

However, this solution does not specify the length of received data, following Nikolai Koudelia's way above, I make a string for received data:

 std::cout << "Received request: [" << std::string(static_cast<char*>(request.data()), request.size())  << "]" << std::endl;
Marquet answered 28/3, 2016 at 6:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.