[Twisted-Python] two twisted clients, how can I trigger the other one's callback in one's callback?

Jean-Paul Calderone exarkun at divmod.com
Wed Jun 20 05:38:51 MDT 2007


On Wed, 20 Jun 2007 03:35:37 -0700 (PDT), slowtech chen <slowtech.chen at yahoo.com> wrote:
>I have 2 clients, one gets a message from a server, once I get the message, I want to send it with the other client to another server. how can i do this?  can I add some customized events and notice the other client? Thanks.

You need to build this system yourself.  Any protocol instance which needs to
be able to interact with another protocol instance needs a reference to that
other protocol instance, either directly (for example, as an attribute on
itself) or indirectly (for example, as an attribute on its factory).  With
this, methods on the other protocol instance can be invoked to send messages.
Here's a trivial example:

    from twisted.internet.protocol import Protocol, ServerFactory
    from twisted.trial.unittest import TestCase


    class BroadcastProtocol(Protocol):
        """
        Protocol which echos received bytes back to all connected
        BroadcastProtocols.
        """
        def dataReceived(self, bytes):
            """
            Handle received bytes by dispatching them to my factory for
            broadcast to all clients.
            """
            self.factory.sendMessage(bytes)


        def sendMessage(self, bytes):
            """
            Write the given bytes to my transport.
            """
            self.transport.write(bytes)



    class BroadcastFactory(ServerFactory):
        """
        Serve and track BroadcastProtocol instances.

        @ivar connectedProtocols: A list of all protocol instances which have
            been returned by buildProtocol.
        """
        protocol = BroadcastProtocol

        def __init__(self):
            self.connectedProtocols = []


        def buildProtocol(self, addr):
            """
            Instantiate my protocol class, append it to my tracking list, and
            return it.
            """
            protocol = ServerFactory.buildProtocol(self, addr)
            self.connectedProtocols.append(protocol)
            return protocol


        def sendMessage(self, bytes):
            """
            Send the given bytes to all tracked protocols.
            """
            for proto in self.connectedProtocols:
                proto.sendMessage(bytes)


    class BroadcastProtocolTests(TestCase):
        """
        BroadcastProtocol should send all bytes it receives to all other
        connected BroadcastProtocol instances.
        """
        def test_buildProtocol(self):
            """
            BroadcastFactory.buildProtocol should return an instance of
            BroadcastProtocol and add that instance to its tracking list.
            """
            factory = BroadcastFactory()
            protocol = factory.buildProtocol(None)
            self.assertEqual(factory.connectedProtocols, [protocol])


        def test_factorySendMessage(self):
            """
            BroadcastFactory.sendMessage should call sendMessage on each
            of the protocols in its tracking list.
            """
            class StubProtocol(object):
                """
                Mimick the message-sending interface of BroadcastProtocol.
                """
                def __init__(self):
                    self.messages = []
                def sendMessage(self, message):
                    self.messages.append(message)

            factory = BroadcastFactory()
            protocol = StubProtocol()
            factory.connectedProtocols = [protocol]
            message = object()
            factory.sendMessage(message)
            self.assertEqual(protocol.messages, [message])


        def test_dataReceived(self):
            """
            BroadcastProtocol.dataReceived should pass whatever bytes it is
            called with to the factory's sendMessage method.
            """
            class StubFactory(object):
                """
                Mimick the message-sending interface of BroadcastFactory.
                """
                def __init__(self):
                    self.messages = []
                def sendMessage(self, message):
                    self.messages.append(message)
            factory = StubFactory()
            protocol = BroadcastProtocol()
            protocol.factory = factory
            message = object()
            protocol.dataReceived(message)
            self.assertEqual(factory.messages, [message])


        def test_protocolSendMessage(self):
            """
            BroadcastProtocol.sendMessage should write the bytes it is called
            with to its transport.
            """
            class StubTransport(object):
                """
                Mimick a transport sufficiently for the purposes of simple
                writes.
                """
                def __init__(self):
                    self.messages = []
                def write(self, bytes):
                    self.messages.append(bytes)
            protocol = BroadcastProtocol()
            transport = StubTransport()
            protocol.makeConnection(transport)
            message = object()
            protocol.sendMessage(message)
            self.assertEqual(transport.messages, [message])

Jean-Paul




More information about the Twisted-Python mailing list