4

I am trying to use JeroMQ from MATLAB,
by implementing this example ( How to use jeromq in MATLAB ):

% Author : Dheepak Krishnamurthy
% License : BSD 3 Clause

import org.zeromq.ZMQ;

ctx = zmq.Ctx();

socket = ctx.createSocket(ZMQ.REP);

socket.bind('tcp://127.0.0.1:7575');

message = socket.recv(0);

json_data = native2unicode(message.data)';

message = zmq.Msg(8);
message.put(unicode2native('Received'));

socket.send(message, 0);
socket.close()

The script runs until line:

message = socket.recv(0);

but stucks there.

MATLAB would then not respond anymore and has to be killed with Task Manager.

Can someone give a hint, if there are additional things to do, in order to get this running?

Community
  • 1
  • 1
Dan
  • 93
  • 5

1 Answers1

4

JeroMQ call signatures state:

        /**
         * Receive a message.
         *
         * @return the message received, as an array of bytes; null on error.
         */
        public final byte[] recv()
        {
            return recv(0);
        }

        /**
         * Receive a message.
         *
         * @param flags
         *            the flags to apply to the receive operation.
         * @return the message received, as an array of bytes; null on error.
         */
        public final byte[] recv(int flags)
        {
            zmq.Msg msg = base.recv(flags);

            if (msg != null) {
                return msg.data();
            }

            mayRaise();
            return null;
        }

        /**
         * Receive a message in to a specified buffer.
         *
         * @param buffer
         *            byte[] to copy zmq message payload in to.
         * @param offset
         *            offset in buffer to write data
         * @param len
         *            max bytes to write to buffer.
         *            If len is smaller than the incoming message size,
         *            the message will be truncated.
         * @param flags
         *            the flags to apply to the receive operation.
         * @return the number of bytes read, -1 on error
         */
        public final int recv(byte[] buffer, int offset, int len, int flags)
        {
            zmq.Msg msg = base.recv(flags);

            if (msg != null) {
                return msg.getBytes(0, buffer, offset, len);
            }

            return -1;
        }

Your code uses the 2nd one:
public final byte[] recv( int flags ){...}

for which your code injects a hardcoded integer value of 0 for the flags parameter.

Next,
the int flags meaning is better documented in API as:

The flags argument is a combination of the flags defined below:
ZMQ_NOBLOCK
Specifies that the operation should be performed in non-blocking mode. If there are no messages available on the specified socket, the zmq_recv() function shall fail with errno set to EAGAIN.

With due care, one may use DONTWAIT flag inside JeroMQ, but some other meaningful options are hard to find from bottom up.

So finally,
let's read the ZeroMQ defined
and recognised set of flags:

// ------------------------------------------------- // Socket options.                                                           
#define ZMQ_HWM                1
#define ZMQ_SWAP               3
#define ZMQ_AFFINITY           4
#define ZMQ_IDENTITY           5
#define ZMQ_SUBSCRIBE          6
#define ZMQ_UNSUBSCRIBE        7
#define ZMQ_RATE               8
#define ZMQ_RECOVERY_IVL       9
#define ZMQ_MCAST_LOOP        10
#define ZMQ_SNDBUF            11
#define ZMQ_RCVBUF            12
#define ZMQ_RCVMORE           13
#define ZMQ_FD                14
#define ZMQ_EVENTS            15
#define ZMQ_TYPE              16
#define ZMQ_LINGER            17
#define ZMQ_RECONNECT_IVL     18
#define ZMQ_BACKLOG           19
#define ZMQ_RECOVERY_IVL_MSEC 20   /*  opt. recovery time, reconcile in 3.x   */
#define ZMQ_RECONNECT_IVL_MAX 21

// ------------------------------------------------- // Send/recv options.                                                        
#define ZMQ_NOBLOCK 1    // <<<<<<<<<<<<<<<<<<<<<<<<<<- THIS ONE IS NEEDED
#define ZMQ_SNDMORE 2

// ------------------------------------------------- // I/O Multplexing options.
#define ZMQ_POLLIN  1
#define ZMQ_POLLOUT 2
#define ZMQ_POLLERR 4

// ------------------------------------------------- // Device types.
#define ZMQ_STREAMER  1
#define ZMQ_FORWARDER 2
#define ZMQ_QUEUE     3

EPILOGUE:

If using .recv( 0 ) your code will BLOCK, until the socket-instance indeed receives anything .recv()-able in the local-side from any, possibly existing in some near or farther future, compatible, .connect()-ed remote end ( a REQ socket et al ).

If using .recv( 1 ) your code will NOT BLOCK, but one should properly handle both possible return-states { <msg.data()_Value> | (EXC, NULL) } and consult with ZeroMQ errno details, to act in accord with the signalled situation context.

halfer
  • 19,824
  • 17
  • 99
  • 186
user3666197
  • 1
  • 6
  • 50
  • 92
  • ★★★★☆ -- Good answer. The **Epilogue** in particular was very moving. 8/10. Would recommend. – Tasos Papastylianou Sep 05 '16 at 11:56
  • 2
    [ a *mandatory* piece of cake for you, Tasos ] Glad you have enjoyed the story. Going into heterogeneous distributed systems is a thrilling experience for even seasoned hackers. It is not easy to guess and fit the level-of-detail and the long vertical stacks may wreck havoc in so many places... Sometimes the longer way around the issue helps more, than a straightforward, but short-sighted notice about a root cause in using rather `NOBLOCK` instead of omnipotent meaning of `0`. – user3666197 Sep 05 '16 at 14:10
  • hahahah, I wholeheartedly agree! I just found the word **epilogue** a bit funny; it gives the whole answer a rather sombre, literary tone :p "Thus became of our heroes ... join us again next week, for more daring adventures in distributed systems design!" \o/ – Tasos Papastylianou Sep 05 '16 at 15:15