0

In the TCP client example:

from twisted.internet import reactor, protocol


# a client protocol

class EchoClient(protocol.Protocol):
    """Once connected, send a message, then print the result."""

    def connectionMade(self):
        self.transport.write("hello, world!")

    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        print "Server said:", data
        self.transport.loseConnection()

    def connectionLost(self, reason):
        print "connection lost"

class EchoFactory(protocol.ClientFactory):
    protocol = EchoClient

    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"
        reactor.stop()

    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"
        reactor.stop()


# this connects the protocol to a server runing on port 8000
def main():
    f = EchoFactory()
    reactor.connectTCP("localhost", 8000, f)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()

I have a periodic task that needs to send data to the server. All the logic for the task is outside the Protocol and Factory. Is it bad form to pass around f and use f.protocol.transport.write("Something?")?

nickponline
  • 25,354
  • 32
  • 99
  • 167

2 Answers2

2

You can restructure your code and take advantage of some new-ish APIs to avoid having to do extra work in the factory to accomplish your goals. Mike Lutz's answer is perfectly correct and what I used to suggest to people before endpoints. Now that we have endpoints, I suggest that people use those instead.

The endpoint APIs let you write a main function that looks more like this:

def main():
    e = HostnameEndpoint(reactor, "localhost", 8000)
    f = EchoFactory()
    d = e.connect(f)
    d.addCallback(connected)
    return d

def connected(protocol):
    # protocol is an instance of EchoClient and is connected
    return LoopingCall(doStuff, protocol).start(3)

You might also consider adapting this to use twisted.internet.task.react which will take care of some of the reactor bookkeeping for you.

Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
0

I'm new-ish to the Twisted world too, so take me with a grain of salt, but I say its acceptable form.

See the following SO were I gave an example of how to hook parts of twisted together: Persistent connections in twisted. (as it happens that answer talks about periodic tasks too...)

EDIT

Ooops, wait. You have a factory in there.

The factory is making a new instance of the the protocol each time there is a connection, so your f.protocol.transport.write won't work (the protocol will point to the class, not a connected instance of the class). Try running my code sample from the Persistent connections question, I make a connection list (the self.clients in the factory), using that structure you can use the .write of the various connections by iterating through the connection list

Community
  • 1
  • 1
Mike Lutz
  • 1,812
  • 1
  • 10
  • 17