Hot questions for Using ZeroMQ in ubuntu

Question:

For installation of ZeroMQ on Linux-Ubuntu , one website

https://tuananh.org/2015/06/16/how-to-install-zeromq-on-ubuntu/

says to run following commands :

sudo apt-get install libtool pkg-config build-essential autoconf automake

sudo apt-get install libzmq-dev

in which we are installing libzmq-dev seperately. Whereas according to

http://zeromq.org/intro:get-the-software

"Make sure that libtool, pkg-config, build-essential, autoconf, and automake are installed." So we dont need to install libzmq-dev explicity.

So my question is what difference does it make? what is the use of libzmq? Is it different from libzmq-dev ? If I want to code in C++ , then do I need to install both libzmq and cppzmq ,as given in https://github.com/zeromq/cppzmq .

And please tell which header file( zmq.h ,zmq.hpp and zhelpers.hpp ) comes from which library?


Answer:

libzmq contains the zmq library only (libzmq.so, libzmq.a).

libzmq-dev contains the library and also C header file (zmq.h). If you want to develop with zmq, you need to use this one instead of libzmq.

"Make sure that libtool, pkg-config, build-essential, autoconf, and automake are installed." So we dont need to install libzmq-dev explicity.

These tools are needed if you want to build libzmq from source code. No need to do that if you install via apt.

cppzmq is C++ binding for zmq so you can use C++ stuffs to work with ZMQ instead via C api that libzmq provide.

zmq.h from libzmq-dev, zmq.hpp and zhelpers.hpp from cppzmq.

Question:

I have a ZeroMQ PUB/SUB connection between a server and clients written in Python. The server sends a message and the client prints it out.

These programs work perfectly fine in the same computer ( either Ubuntu 16.04, or Windows 7; both work ).

They also work when the server is on the Windows 7 machine and the client is on the Ubuntu 16.04 machine.

However, if the server is on the Ubuntu 16.04 machine then the client on the Windows 7 machine cannot connect to it.

Also, there is not a problem of communication when I move the client and server programs between two separate Windows 7 machines.

Does anyone know what the problem might be?

Here is the client code:

#Based on code found on this Stack Overflow post:
#https://stackoverflow.com/questions/43817161/how-to-send-opencv-video-footage-over-zeromq-sockets

import cv2
import zmq
import base64
import numpy as np

context = zmq.Context()
footage_socket = context.socket(zmq.SUB)
address = 'tcp://192.168.128.229:5555'
footage_socket.connect(address)
footage_socket.setsockopt_string(zmq.SUBSCRIBE, unicode(''))

print "start"
print "connecting to ", address

while True:
    try:
        frame = footage_socket.recv_string()
        img = base64.b64decode(frame)
        npimg = np.fromstring(img, dtype=np.uint8)
        source = cv2.imdecode(npimg, 1)
        cv2.imshow("image", source)
        cv2.waitKey(1)

    except KeyboardInterrupt:
        cv2.destroyAllWindows()
        print "\n\nBye bye\n"
        break

Here is the server code:

#Based on code found on this Stack Overflow post:
#https://stackoverflow.com/questions/43817161/how-to-send-opencv-video-footage-over-zeromq-sockets

import cv2
import zmq
import base64

context = zmq.Context()
footage_socket = context.socket(zmq.PUB)
footage_socket.bind('tcp://*:5555')
footage_socket.setsockopt(zmq.CONFLATE, 1)

camera = cv2.VideoCapture(0)

while True:
    try:
        (grabbed, frame) = camera.read()
        frame = cv2.resize(frame, (640, 480))
        encoded, buffer = cv2.imencode('.png', frame)
        footage_socket.send_string(base64.b64encode(buffer))


    except KeyboardInterrupt:
        camera.release()
        cv2.destroyAllWindows()
        print "\n\nBye bye\n"
        break

Answer:

A list of Best Practices:
  • Interpretation: do not rely on re-dressing into a string-wrapped original content ( has made a lot issues once string became a byte in post Python-3.0+ )
  • Version control: not all versions of ZeroMQ core-facilities have the same modus-operandi ( PUB/SUB topic filtering happens on PUB side in recent versions, whereas was operated on SUB side, in the ZeroMQ earlier days. Versions do matter.
  • Performance: avoid as much overhead "external" to the core-flow of data as possible. Using base64.{b64encode()|b64decode()} is an example of such an adverse performance comfort, without delivering any adequate benefit.

  • Profile, tune and check the real costs of any cv2-based frame processing ~ colour-space conversions may take +170 [ms] p.i. ( in lower-left window )

  • May add any further details in a very cheap fashion right into aMessagePAYLOAD ( via struct.pack( aPayloadMASK, .data, OptionA, OptionB, OptionC ) - be it a rotating aSeqNumUINT8, aUsecTimeSTAMP, or whatever else one may like to add )

Do-s PUB-side:
import numpy as np
import zmq
import cv2
import struct

print( "INF: this process uses {0: >10s} v.{1:}".format(  "ZMQ",  zmq.__version__ ) )
print( "INF: this process uses {0: >10s} v.{1:}".format(  "NUMPY", np.__version__ ) )
...
..
aPubSOCKET.setsockopt( zmq.LINGER,        0 )
aPubSOCKET.setsockopt( zmq.IMMEDIATE,     1 )
aPubSOCKET.setsockopt( zmq.TOS,           aTypeOfSERVICE_PREFERENCE_ID )
aPubSOCKET.setsockopt( zmq.SNDHWM,        4 )
aPubSOCKET.setsockopt( zmq.SNDBUF,        4*640*480*3 )
aPubSOCKET.setsockopt( zmq.CONFLATE,      1 )
...
..
.
aPayloadMAP = ">"+ ( 640 * 480 * 3 )*"B"
HiResCAM    = cv2.VideoCapture( 0 )

while True:
      try:
          ( _ , cv2HiResFRAME ) = HiResCAM.read()    # acquire FRAME
          aPubSOCKET.send( struct.pack( aPayloadMAP, # pack to aMsgPAYLOAD, once .resize()'d
                                        cv2.resize( cv2HiResFRAME,
                                                    ( 640, 480 )
                                                    ).data
                                        ),           # OpenCV 2.2+ natively uses numpy arrays W * H * D * unit8 in BGR-ordering ( BGRA, if alpha used )
                           zmq.NOBLOCK
                           )

      except KeyboardInterrupt:
            # ...

      finally:
            # gracefully terminate all OpenCV resources
            # gracefully terminate all ZeroMQ resources
            break

Do-s SUB-side:
import numpy as np
import zmq
import cv2
import struct

print( "INF: this process uses {0: >10s} v.{1:}".format(  "ZMQ",  zmq.__version__ ) )
print( "INF: this process uses {0: >10s} v.{1:}".format(  "NUMPY", np.__version__ ) )
...
..
aSubSOCKET.setsockopt( zmq.LINGER,        0 )
aSubSOCKET.setsockopt( zmq.CONFLATE,      1 )
aSubSOCKET.setsockopt( zmq.MAXMSGSIZE,  100+640*480*3 )
aSubSOCKET.setsockopt( zmq.RCVHWM,        4 )
aSubSOCKET.setsockopt( zmq.RCVBUF,        4*640*480*3 )

aSubSOCKET.connect(                       address )
aSubSOCKET.setsockopt( zmq.SUBSCRIBE,    "" )

aPayloadMASK = ">" + ( 640 * 480 * 3 * "B" )

while True:
      try:
            cv2.imshow( "LAST IMAGERY AVAILABLE:",  struct.decode( aPayloadMASK, aSubSOCKET.recv() )
            cv2.waitKey( 1 )

      except KeyboardInterrupt:
            # ...

      finally:
            # gracefully terminate all OpenCV resources
            # gracefully terminate all ZeroMQ resources
            break

Question:

I have installed pyzmq by pip install pyzmq,then I found a bug in libzmq 4.1.6 which has been fixed in libzmq 4.2.*(issue) . So how can I upgrade libzmq ?

env: libzmq-4.1.6 pyzmq-16.0.3 Python-3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609]


Answer:

You'll probably need to build PyZMQ again against the new libzmq 4.2. I've used this guide with success.

Question:

I'm trying to install zeromq but I'm having some problems with undefined reference . I used this tutorial to install zeromq in my machine, with the difference that I downloaded version 4.1.4 and not 4.1.2.

Then I'm trying to run the following code (got from zeromq tutorial) in C:

//  Hello World server

#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

int main (void)
{
    //  Socket to talk to clients
    void *context = zmq_ctx_new ();
    void *responder = zmq_socket (context, ZMQ_REP);
    int rc = zmq_bind (responder, "tcp://*:5555");
    assert (rc == 0);

    while (1) {
        char buffer [10];
        zmq_recv (responder, buffer, 10, 0);
        printf ("Received Hello\n");
        sleep (1);          //  Do some 'work'
        zmq_send (responder, "World", 5, 0);
    }
    return 0;
}

with this line:

gcc program.c -lzmq

and I got this error:

/tmp/cc3OkNsE.o: In function `main':
program.c:(.text+0x18): undefined reference to `zmq_ctx_new'
collect2: error: ld returned 1 exit status

I already did some research but I couldn't find any clear solutions/instructions. Anyone knows how to solve it or what I'm doing wrong?


Answer:

As pointed by Maarten Artis in the comments above, it wasn't actually linking the library. The correct command line is:

gcc -Wall program.c -o prog -L/usr/local/lib -lzmq