andrewvc / em-zeromq

ZeroMQ on EventMachine

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

req/rep not working properly

filterfish opened this issue · comments

I've set up a req/rep pair (code below) but it's not working as I would expect it. If I run the client without a server then I get a response; I would expect to only get a response if the server sends one!

The interesting thing is that if the server is running the client will print "Got return message", the reactor will shut down and the program will correctly terminate. If the server is not running the client will print "Got return message", and then it will wait (I assume it's waiting for the return message). If I subsequently start the server then the client will properly terminate.

############## Client

require 'em-zeromq'

class Handler
def on_writable(socket)
puts "Got return message"
socket.unbind
EM.stop
end
end

EM.run do
context = EM::ZeroMQ::Context.new(1)

socket = context.connect(ZMQ::REQ, 'tcp://127.0.0.1:2091', Handler.new)
puts "sending ready message"
socket.send_msg("ready?")
end

############## Server

require 'em-zeromq'

class Handler
def on_readable(socket, messages)
socket.send_msg "ready"
end
end

EM.run {
handler = nil
context = EM::ZeroMQ::Context.new(1)

context.bind(ZMQ::REP, 'tcp://127.0.0.1:2091', Handler.new)
}

Hi,
I am a little confused with your client code, your are waiting until the socket becomes writeable to print a message saying you received a message ? Did you meant on_readable ?

If the text printed are wrong and what you were expecting is that the socket becomes writeable only if there is a server on the other side I do not think it will work that way since zeromq manages the send queue itself, on our side the socket will be immediately writeable and will become no longer writeable only when the zeromq queue is full.

Maybe your code would work as expected if you set the send queue size to 0 but it would completely defeat the purpose of using zeromq.

Agreed w/ schmurfy, you want to hook into on_readable for a req socket, since a req_socket is only readable after a reply has come through.

If I use on_readable I never get anything back. I can see the reply on the network (using wireshark) but notify_readable is simply never called and consequently neither is on_readable.

There is indeed something broken with REQ/REP while XREQ/XREP work fine, I can see the packet coming at the network level like you but it never triggers the callback. I started looking into it but found nothing yet, I was using zeromq 2.1.6.
@filterfish : which zeromq version did you tried with ? I t may help fix this.

I'll take a look at this later today, but I should mention, xreq/xrep are a much better match for eventmachine. Is there a reason you need blocking behavior?

@schmurfy I used version 2.1.4 (Debian experimental).

@andrewvc What I'm actually after is to have a way on knowing if there is a listener when sending messages. PUSH would be ideal but with em-zeromq messages are discarded if there is no listener. If I remove the ZMQ::NOBLOCK in Connection#send_msg then the sender blocks but obviously this blocks the whole reactor. Is there a way of having the call to Connection#send_msg block but not block the reactor much in the same way as Context#connect blocks but doesn't block the reactor?

Sending messages with zeromq is never blocking (in the nomal case at least), that is one of the feature of this library, as you pointed it is true that the power zeromq gives us does come with a price: you never known if there is someone on the "other side" of the connection when you send a message.
What happens when you send a message depends on the type of socket you used, you can check here for a complete reference of the sockets types and their behaviors: http://api.zeromq.org/2-1:zmq-socket .
For REQ/XREQ the messages are queued until a listener appears if I remember well.

You can check http://zguide.zeromq.org/page:all, there are great examples of real architecture applied to zeromq, it may helps you find a way to fit your needs with zeromq.

I redid some tests and I am starting to wonder if the problem is not that the fake FD zeromq returns to us just not work as expected with REP/REQ in the 2.1.6 release.
I tried simple blocking read/write tests with ffi-rzmq and they worked as expected.

Hmmm, that's possible. My understanding of how those FDs work is that 0MQ uses them internally to signal communications (like message arrived). Any chance you could gist the tests schmurfy?

BTW, the fake FDs are actually unix sockets.

I have no test that shows a failure, what I did is check that REP/REQ where actually working as intended both in C and with ffi-rzmq, here are both tests if they can be of any use: https://gist.github.com/961468 .

Pending new information, this doesn't seem to be an actual issue.