[zeromq-dev] Can't bind same ZMQ_UP/DOWNSTREAM multiple times.
Matt Weinstein
matt_weinstein at yahoo.com
Tue Aug 17 14:02:17 CEST 2010
I thought this is what the :
REQ =(*)= XREP==DEVICE==XREQ== REP
pattern is for.
Just have your clients connect() to the socket on the left half of the
device (which is the left half of the device and is a bind().
On Aug 17, 2010, at 12:39 AM, Oliver Smith wrote:
> 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
>
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
More information about the zeromq-dev
mailing list