[Twisted-Python] Create client in Server factory
Kevin Horn
kevin.horn at gmail.com
Wed Oct 31 08:31:32 MDT 2012
On Wed, Oct 31, 2012 at 4:49 AM, Phil Mayers <p.mayers at imperial.ac.uk> wrote:
> On 10/31/2012 07:14 AM, Grégoire Leroy wrote:
>> Hi,
>>
>> I have a server who receive data from clients A/B/C (remote machines). I want
>> to use a client D (on the same machine than the server) to send this data to
>> another server (remote).
>>
>> The difficulty is, I want to use the same client D connection for any client. I
>> don't want open an new connection each time.
>>
>> First thing I would think is to create the connection in my server factory,
>> and use client's methods in my server protocol, for example with
>> [...]
>> class LocalProxyFactory(Factory):
>> def __init__(self):
>> f = LocalProxyClientFactory()
>> reactor.connectTCP("retenodus.net", 4242, f)
>> reactor.run()
>
> The "reactor.run" is just wrong - remove it.
>
> You need to connect to a server, and share this connection amongst some
> protocols. But you can't control the order in which these connections
> complete, so A/B/C might connect before D is ready.
>
> You've really got two choices - accept the connections from A/B/C but
> have your server protocol "wait" until D is ready - something like this:
>
> from twisted.internet.protocol import ClientCreator
>
> class Server(...):
> def connectionMade(self):
> if self.factory.connD is None:
> self.factory.waitFor(self._ready)
> self.transport.pauseProducing()
>
> def _ready(self):
> self.transport.resumeProducing()
>
> d_connect = ClientCreator(reactor, DProtocol)
>
> class ServerFactory(...):
> def __init__(self):
> self.connD = None
> self._wait = []
> d_connect.connectTCP(Dhost, port).addCallback(self.dReady)
>
> def waitFor(self, _cb):
> if self.connD:
> _cb(self.connD)
> else:
> d = defer.Deferred()
> d.addCallback(_cb)
> self._wait.append(d)
>
> def dReady(self, proto):
> self.connD = proto
> cb = self._wait
> self._wait = []
> for c in cb:
> c.callback(proto)
>
> def main():
> reactor.listenTCP(..., ServerFactory())
> reactor.run()
>
> ...or don't start listening until D has connected, like this:
>
> class ServerFactory(...):
> def __init__(self, dProto):
> self.connD = dProto
>
> def startListen(dProto):
> reactor.listenTCP(..., ServerFactory(dProto))
>
> def main():
> d_connect.connectTCP(Dhost, port).addCallback(startListen)
> reactor.run()
>
> The latter is simpler, but which is appropriate depends on your needs.
>
> Note that I've used ClientCreator to get a callback when the connection
> to D is ready - remember that doesn't happen immediately.
>
See also:
http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#HowdoImakeinputononeconnectionresultinoutputonanother
That example only uses a single connection in place of your clients
A/B/C, but should be adaptable to your situation.
--
Kevin Horn
More information about the Twisted-Python
mailing list