[zeromq-dev] libev and ZMQ
Arun Athrey Chandrasekaran
achandr8 at ncsu.edu
Sat Mar 6 22:49:47 CET 2021
Arnaud,
Following up on my previous email, please see samples of my
client and server codes attached showing how I use the ZMQ APIs. The
endpoints are TCP-based. The client sends a message over the REQ socket and
expects a response from the server over the SUB socket. The server routine
gets called on socket activity and after a ZMQ poll, it responds according
to the received message over the PUB socket. After the server is done with
recv/send, it does a ZMQ poll (which is expected to do this: "....*applications
must retrieve the actual event state with a subsequent retrieval of the
'ZMQ_EVENTS' option."* )
Thanks,
*Arun*
On Thu, Feb 25, 2021 at 12:54 PM Arun Athrey Chandrasekaran <
achandr8 at ncsu.edu> wrote:
> Arnaud,
> As you correctly point out,
>
>
>
> *"The ability to read from the returned file descriptor does not
> necessarily indicate that messages are available to be read from, or can be
> written to, the underlying socket; applications must retrieve the
> actualevent state with a subsequent retrieval of the 'ZMQ_EVENTS' option."*
>
> This may be causing the problem. Even after the client sends a message and
> the server responds, I get one or two more calls from libev. In the
> callback though, I do a ZMQ poll which comes back with no events. My client
> code is in golang and my server code is in C++. After receive and send I do
> a ZMQ poll in the server to take care of this:
>
> "applications must retrieve the actual event state with a subsequent
> retrieval of the 'ZMQ_EVENTS' option"
>
> I don't know if the client should do something after send/receive and
> FWIW, I have tried a few different APIs in golang to achieve the above but
> to no avail.
>
> Thanks,
> *Arun*
>
>
>
> On Thu, Feb 25, 2021 at 12:27 PM Arnaud Loonstra <arnaud at sphaero.org>
> wrote:
>
>> On 25-02-2021 19:35, Arun Athrey Chandrasekaran wrote:
>> > Hi all,
>> > Are there any gotchas w.r.t using libev with ZMQ? I want to
>> > use ZMQ to receive and send messages from/to another process and
>> > instead of a ZMQ server in an infinite loop listening for incoming
>> > requests, I want to use libev to look for socket activity. What I have
>> > found out so far is that even when there is no real socket activity, I
>> > still get "ghost" callbacks from libev. I tried updating the ZMQ_EVENTS
>> > on both client and server sides after ZMQ recv and send but that did
>> not
>> > help.
>> >
>> > Thanks,
>> > *Arun*
>> >
>>
>> Hi Arun,
>>
>> If you have some concept code it would really help. You can use zeromq
>> in any event system which is able to poll on file descriptors. There are
>> some caveats you have to be aware of. I'm not sure how this is done with
>> the newer threadsafe sockets though.
>>
>> From
>>
>> https://github.com/zeromq/libzmq/blob/2bf998f7e0aa19e89918627d386d526e4f2e25dd/doc/zmq_getsockopt.txt
>> "
>>
>> The 'ZMQ_FD' option shall retrieve the file descriptor associated with the
>> specified 'socket'. The returned file descriptor can be used to
>> integrate the
>> socket into an existing event loop; the 0MQ library shall signal any
>> pending
>> events on the socket in an _edge-triggered_ fashion by making the file
>> descriptor become ready for reading.
>>
>> NOTE: The ability to read from the returned file descriptor does not
>> necessarily indicate that messages are available to be read from, or can
>> be
>> written to, the underlying socket; applications must retrieve the actual
>> event
>> state with a subsequent retrieval of the 'ZMQ_EVENTS' option.
>>
>> NOTE: The returned file descriptor is also used internally by the
>> 'zmq_send'
>> and 'zmq_recv' functions. As the descriptor is edge triggered,
>> applications
>> must update the state of 'ZMQ_EVENTS' after each invocation of 'zmq_send'
>> or 'zmq_recv'.To be more explicit: after calling 'zmq_send' the socket may
>> become readable (and vice versa) without triggering a read event on the
>> file descriptor.
>>
>> CAUTION: The returned file descriptor is intended for use with a 'poll' or
>> similar system call only. Applications must never attempt to read or
>> write data
>> to it directly, neither should they try to close it.
>>
>>
>> Rg,
>>
>> Arnaud
>> _______________________________________________
>> zeromq-dev mailing list
>> zeromq-dev at lists.zeromq.org
>> https://lists.zeromq.org/mailman/listinfo/zeromq-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20210306/2f642cfe/attachment.htm>
-------------- next part --------------
zmq_pollitem_t sample_poller[] = { {rep_sock, 0, ZMQ_POLLIN, 0} };
int len_of_poller = (int)(sizeof(sample_poller) / sizeof(zmq_pollitem_t));
rc_poll = zmq_poll(sample_poller, len_of_poller, 0);
if (rc_poll > 0) {
if (sample_poller[0].revents & ZMQ_POLLIN) {
memset(&msg, 0, sizeof(msg));
rc = zmq_msg_init(&msg);
if (rc < 0) {
goto poll_n_quit;
}
do {
rc = zmq_recvmsg(rep_sock, &msg, ZMQ_NOBLOCK);
} while ((rc < 0) && (errno == EINTR));
if (rc < 0) {
goto poll_n_quit;
}
/* Process the message and produce a response "resp" */
rc = zmq_msg_init_size(&resp, resp_len);
if (rc < 0) {
break;
}
do {
rc = zmq_sendmsg(pub_sock, &resp, ZMQ_NOBLOCK);
} while ((rc < 0) && (errno == EINTR));
}
}
poll_n_quit:
rc_poll = zmq_poll(sample_poller, len_of_poller, 0);
zmq_msg_close(&msg);
zmq_msg_close(&resp);
return;
-------------- next part --------------
Client Routine in golang:
ZMQSendAndRecv(SendEndpoint, RecvEndpoint, mesg, requestTimeout)
{
clientRep, _ := zmq.NewSocket(zmq.REQ)
clientRep.Connect(SendEndpoint)
clientSub, _ := zmq.NewSocket(zmq.SUB)
clientSub.SetSubscribe("")
clientSub.Connect(RecvEndpoint)
poller := zmq.NewPoller()
clientRep.SendMessage(mesg)
poller.Add(clientRep, zmq.POLLIN)
polled, err := poller.Poll(requestTimeout)
if len(polled) != 1 {
err = errors.New("Request timed out")
return
}
_, err = clientRep.RecvMessage(0)
if err != nil {
err = errors.New("Failed to get reply")
return
}
msg, err = clientSub.RecvMessageBytes(0)
if err != nil {
err = errors.New("Failed to get reply")
return
}
return
}
More information about the zeromq-dev
mailing list