[zeromq-dev] Can't bind same ZMQ_UP/DOWNSTREAM multiple times.

Oliver Smith oliver at kfs.org
Tue Aug 17 06:39:05 CEST 2010


  On 8/16/2010 12:07 PM, Pieter Hintjens wrote:
> Hi Oliver,
>
> I can repeat my previous reply.  After reading your email I still
> don't understand why you need to bind to the same endpoint twice, and
> why you expect this to work (it won't).
>
> You cannot bind two sockets to a single endpoint.  It's not a legal semantic.
>
> So what in fact is your question?  Sorry if I missed it.
I did do a good job of making that a bit hidden.

The question: What is the right pattern for doing this -- 1 -> N -> M -> 
1 four stage parallelism.

Why it's even a question: Remember, "ZeroMQ sockets aren't /sockets/". 
That just happens to be one of the underlying mechanisms.

 From a networking perspective, I understand why multiple binds don't 
work. And setting SO_REUSEADDR would just be messy...

But I would have thought that internally if multiple socket_ts tried to 
bind to the same IP socket address ///via the same context/// you would 
have handled that internally the same way that you handle multiple 
connects: thus allowing multiple threads within an application to 
service the same socket.

Consider:

8x--- snip ---x8
import zmq
import re

ctx = zmq.Context(8)

class HTTPWorker(threading.Thread):
     def __init__(self):
         threading.Thread.__init__(self)
         self.daemon = True
         self.sock = ctx.socket(zmq.REP)
         self.sock.bind("tcp://0.0.0.0:80")

     def run(self):
         urlMatch = re.compile(r'^GET\s+([/a-zA-Z0-9_.%-]+)')
         while True:
             msg = self.sock.recv()
             matches = urlMatch.match(msg)
             if matches and matches.group(1):
                 content = readFile(matches.group(1))
                 reply = headers(matches.group(1), content)
                 self.sock.send(reply)
8x--- snip ---x8

This would allow one processes to have multiple threads servicing a 
single TCP socket endpoint without the need to go through a device or 
have the operator fork multiple processors.

I do absolutely understand why "self.sock.bind(same address multiple 
times)" on a single machine does not work. But that requires the 
end-user to be aware of the underlying network basis of the function of 
"bind".

Now consider:

     # X threads are going to receive transparently
     # multiplexed work from Q sources.
     self.workin = ctx.socket(zmq.DOWNSTREAM)
     self.workin.connect("inproc://stage1-worker")

     # Those X stage1 workers are going to forward
     # additional work to Y transparently
     # multiplexed stage 2 workers.
     self.workout = ctx.socket(zmq.UPSTREAM)
     self.workout.bind("inproc://stage2-workers")

Again -- I understand why, under the hood, BSD's bind(3) function 
returns address already in use.

But I'm not using bind(3), I'm using zmq->context->bind. Therefore the 
answer to the question should be in ZeroMQ context terms and not 
sockets-api terms... If the answer was "because they are using different 
contexts, and only one context can bind to a socket address" - that 
would work. But "only one endpoint can bind to a socket address even on 
the same context as the other endpoint" doesn't... Certainly not in many 
sample use cases.

- Oliver




More information about the zeromq-dev mailing list