2

I need to add a timeout for the reply/request transaction using 0MQ. How is this typically accomplished? I tried using the method :

socket.setReceiveTimeOut();

and

socket.setSendTimeout();

but they seem to cause a null pointer exception.

In essence, I want the application to timeout after 10 seconds if the application receiving the request is not available.

Any help is appreciated.

Thanks!

user3666197
  • 1
  • 6
  • 50
  • 92
Oscar
  • 31
  • 3

3 Answers3

1

I think jzmq should throw a ZMQException when recv timeout, But there is no ZMQException, when err = EAGAIN.

https://github.com/zeromq/jzmq/blob/master/jzmq-jni/src/main/c%2B%2B/Socket.cpp

static
zmq_msg_t *do_read(JNIEnv *env, jobject obj, zmq_msg_t *message, int flags)
{
    void *socket = get_socket (env, obj);

    int rc = zmq_msg_init (message);
    if (rc != 0) {
        raise_exception (env, zmq_errno());
        return NULL;
    }

#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
    rc = zmq_recvmsg (socket, message, flags);
#else
    rc = zmq_recv (socket, message, flags);
#endif
    int err = zmq_errno();
    if (rc < 0 && err == EAGAIN) {
        rc = zmq_msg_close (message);
        err = zmq_errno();
        if (rc != 0) {
            raise_exception (env, err);
            return NULL;
        }
        return NULL;
    }
    if (rc < 0) {
        raise_exception (env, err);
        rc = zmq_msg_close (message);
        err = zmq_errno();
        if (rc != 0) {
            raise_exception (env, err);
            return NULL;
        }
        return NULL;
    }
    return message;
}
zmag
  • 7,825
  • 12
  • 32
  • 42
Yacheng Zhou
  • 53
  • 1
  • 4
0

How is this [a timeout for the reply/request transaction] typically accomplished ?

I am sad to confirm, there is nothing like this in the ZeroMQ native API. The principle of doing async delivery means, there is no limit for delivery to take place ( in a best-effort model of scheduling, or not at all ).


If new to the ZeroMQ, you may enjoy a fast read into this 5-second read about the main conceptual elements in [ ZeroMQ hierarchy in less than a five seconds ] Section.

I want ... to timeout after 10 seconds if ... receiving the request is not ...

May design your .recv()-method call usage into either a pre-tested / protected after a .poll( 10000 )-method screener, to first explicitly detect a presence of any message for indeed being delivered to your application-code, before ever issuing ( or not ) a call to the actual .recv()-method only upon a previously POSACK-ed message to be ready to get locally read, or may use a bit more "raw" approach, using a handler with a non-blocking form of the method, by a call to the .recv( ZMQ_NOBLOCK )-flagged not to spend a millisecond "there", in cases when "there" are no messages to read right now from the local-side Context()-engine instance, and handle each of the cases accordingly in your code.


A Bonus Point

Also be warned, that using the REQ/REP-Scalable Formal Communication Archetype pattern will not be any easier, as there is a mandatory two-side-step-dance ( sure, if not intentionally artificially ZMQ_RELAXED ), so the both FSA-back-to-back-connected-FSA-s will still have to wait for the next "expected" remote-event, before becoming able to make a chance for handling the next local-event. If interested in details, one will find many posts on un-avoidable, un-salvagable mutual-deadlock, that is sure to happen for REQ/REP, where we only do not know when it happens, but are sure it will.

halfer
  • 19,824
  • 17
  • 99
  • 186
user3666197
  • 1
  • 6
  • 50
  • 92
0

I wonder if your null pointer is related to how your socket was created. I have set a socket timeout successfully in the past.

The following has worked for me when I used the JeroMQ library (native Java implementation of ZMQ). I used this to help do REQ-REP commands via ZMQ.

ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket sock = context.socket(ZMQ.REQ);
sock.setSendTimeOut(10000); // 10 second send timeout
sock.setReceiveTimeOut(10000); // 10 second receive timeout
if (sock.connect("tcp://127.0.0.1:1234")) {
    if (sock.send(/* insert data here */)) {
        /* Send was successful and did not time out. */
        byte[] replyBytes = null;
        replyBytes = sock.recv();
        if (null == replyBytes) {
            /* Receive timed out. */
        } else {
            /* Receive was successful. Do something with replyBytes. */
        }
    }
}
Mike Foss
  • 311
  • 2
  • 6