[zeromq-dev] connection-oriented versus message-pattern oriented

Chuck Remes cremes.devlist at mac.com
Wed May 19 01:02:07 CEST 2010

I just wrote this to a friend of mine who is looking at 0mq. It took me a while to understand 0mq (not sure I really do yet) but his reaction to it left me thinking that this might be useful to someone else. 

Note that I realize that bind & connect aren't *always* flip-flopped but with 0mq I think they will be quite often.



My biggest stumbling block (which I'm not sure I am over yet) is mapping the bind/connect names to the POSIX socket equivalents. In reality they aren't equivalent at all. POSIX sockets are connection oriented while 0mq sockets are message-pattern oriented. One REQ socket may have 5000 TCP sockets behind it depending on how many times it was bound or connected to a new address. 

I think the key to unlocking 0mq's power is in understanding that concept above. Let me run you through a example.

Let's say you want to publish (fanout) a bunch of data to a set of clients, but the clients are transient. Also, some of the clients are on a distant network so they require TCP transport. Other clients are on the local machine, so they can use IPC for better performance. Lastly, there is one client that lives within the same process as your publisher as a separate thread. Here's how you get them all linked up. (You may already know this in which case you can ignore the remainder.)

# examples in ruby
1. Publisher creates a ZMQ_PUB socket.

context = ZMQ::Context.new 5, 5

publisher = ZMQ::Socket.new context, ZMQ::PUB

# bind to tcp transport
publisher.bind "tcp://"

# second port for subscribers outside the firewall
publisher.bind "tcp://"

# bind to ipc transport
publisher.bind "ipc://named_file"

# bind to local thread using inproc transport
publisher.bind "inproc://something"

while true do
 publisher.send random_message

Note that the code above used "bind" for each of these destinations.

The clients will now use those same transport addresses, but instead of binding to them like you would imagine a receiver would do, they *connect* to the transport.

context = ZMQ::Context.new 1, 1

subscriber = ZMQ::Socket.new context, ZMQ::SUB

subscriber.connect "tcp://"

msg = ZMQ::Message.new

while true do
 rc = subscriber.recv msg
 do_work msg

The usual sense of bind and connect are completely flip-flopped. In POSIX sockets, transmitters do a "connect" to some address while receivers "bind" to it. In 0mq, the publisher has no idea how many clients it has nor when they are linked or unlinked. Therefore, the PUB socket can bind to an address and send data to it. If no one ever connects, it hits /dev/null. But any interested subscribers can connect to that address, read all they want, and disconnect at will.

Also note that a *single* PUB socket was created and then bound to multiple destinations. This one 0mq socket has at least 2 TCP sockets proxied by it as well as IPC and inter-thread communications.

Very cool stuff.

I hope that helped.

More information about the zeromq-dev mailing list