How to send message between C++ and Python Program Using ZeroMQ in Raspberry Pi

How to send message between C++ and Python Program Using ZeroMQ in Raspberry Pi

How to send message between C++ and Python Program Using ZeroMQ in Raspberry Pi

First we need the following packages.

  • ZeroMQ
  • gcc 4.8 or later
  • Cmake
  • Pyzmq
How to Install Necessary Packages

1.Follow this link to install ZeroMQ

2.Follow this link to install gcc 4.8

3.Follow this link to install Cmake

4.Follow this link to install Pyzmq

Additional Note

Clinet use connect to connect the server. Server use bind to set its server address. In this post, localhost is used. If you want to connect across the LAN network, localhost can be changed to real IP addess such as "tcp://192.168.1.104:5555"

Writing Client Program With Python

We will create a client program with Python. You can use with your favorite editor (in my case, I’m using gedit)

$ cd ~/
$ mkdir ClientProgram
$ cd ClientProgram
$ gedit client.py

Then paste the following code into gedit editor. Save and exit the program.

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
port = "5555"
socket.connect ("tcp://localhost:%s" % port)

for i in range (1,10):
    socket.send ("saying hello from python")
    message = socket.recv()
    print "Received reply from server:", message
Writing Server Program With C++

In C++, we need more steps to compile. Now we will create server program with C++.

$ cd ~/
$ mkdir ServerProgram
$ cd ServerProgram
$ gedit main.cpp

Then paste the following code into gedit editor. Save and exit the gedit editor.

#include <zmq.hpp>
#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");

    // forever loop
    while (true) {
        zmq::message_t request;

        //  Wait for next request from client
        socket.recv(&request);
        std::string replyMessage = std::string(static_cast<char *>(request.data()), request.size());
//        std::string replyMessage = std::string((request.data())., request.size());
        // Print out received message
        std::cout << "Received from client: " + replyMessage << std::endl;

        //  See the gradual sending/replying from client
        sleep(1);

        //  Send reply back to client
        std::string msgToClient("greeting from C++");
        zmq::message_t reply(msgToClient.size());
        memcpy((void *) reply.data(), (msgToClient.c_str()), msgToClient.size());
        socket.send(reply);
    }
    return 0;
}

Now we will create a CMake File. Assuem that we are still in ServerProgram folder. Type the following command.

$ gedit CMakeLists.txt

Then paste the following code into gedit editor. Then save and exit the program.

cmake_minimum_required(VERSION 3.3)
project(ZmqProject)

# This will file libzmq.so file from /usr/local/lib
FIND_FILE(ZMQLIB libzmq.so /usr/local/lib)
IF(NOT ZMQLIB)
    MESSAGE(SEND_ERROR "Ah.. Cannot find library libzmq.so.")
ENDIF(NOT ZMQLIB)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)

add_executable(ZmqProject ${SOURCE_FILES})
# The following line will link with libzmq.so
TARGET_LINK_LIBRARIES( ZmqProject ${ZMQLIB})

Now we are going to compile the program with CMake. Assume here again that we are still in ServerProgram folder.

$ mkdir tmp
$ cd tmp
$ cmake ..
$ make

After the successful compile, you should see the following lines on terminal.

Scanning dependencies of target ZmqProject
[ 50%] Building CXX object CMakeFiles/ZmqProject.dir/main.cpp.o
[100%] Linking CXX executable ZmqProject
[100%] Built target ZmqProject

Testing both python and c++ program
We will first run the client program first. Go to the ClientProgram folder that we first created. Then run the program.

$ cd ~/
$ cd ClientProgram
$ python client.py

Note: we will note see any output yet since we haven’t run the server program

Here we should get another tab from terminal by pressing Ctrl + Alt +T. Now we go to ServerProgram folder and then run the program.

$ cd ~/
$ cd ServerProgram
$ cd tmp
$ ./ZmqProject

Once the both programs are started to run. you should see these outputs. You should see this output from the server side.

Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python
Received from client: saying hello from python

You should see this output from the client side.

Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++
Received reply from server: greeting from C++

Note: the cleint program will exit once the program finishs the loop. However, the server will keep listening any incoming message. This is how the programs are written.


4 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Very nice...
    I have a problem, I cant resolve.
    I havve zmq publisher in python and zmq subscricriber in c++, but communication is not working. Do you happen to know a working example?

    ReplyDelete
  3. This pretty much worked out of the box for me! Good job. Ran into some incompatability issues with libsodium/zmq but 1.0.12/4.1.4 is a valid combination.

    ReplyDelete
  4. I have this error an I cannot find a way to proceed with the make

    error: ‘socket’ is not captured socket.send(reply);

    What am I missing?

    ReplyDelete