[Twisted-Python] How can I send unique configuration data for multiple connections through a factory?

Mark Bailey mebly5343 at gmail.com
Wed Feb 10 13:53:49 EST 2010


Good day:

I've been having fun with Twisted.  I have my application running fine, with
multiple server and client connections using Telnet.  :-)

However, users always want something.  I need to send some unique
configuration information to each connection.  The connections are made
using connectTCP.  My first attempt assumed that the connection was made
when the call to connectTCP was executed.  It didn't work!  :-(

-------------------------------

from twisted.internet.protocol import ClientFactory
from twisted.internet import reactor
from twisted.conch.telnet import StatefulTelnetProtocol

class testClient(StatefulTelnetProtocol):

    def connectionMade(self):
        self.title = self.factory.connectString
        print "Client Connected: " + self.title
        self.setRawMode()
        self.factory.connections.append(self)

    def connectionLost(self, reason):
        if self in self.factory.connections:
            self.factory.connections.remove(self)

    def rawDataReceived(self,data):
        print data + "\n"

class ClusterClientFactory(ClientFactory):

    protocol = testClient

    def __init__(self):
        self.connections = []
        self.connectString = ''

    def startFactory(self):
        print "startFactory: " + self.connectString

    def startedConnecting(self, connector):
        print "Started connecting: " + str(connector)
        print self.connectString

    def buildProtocol(self, addr):
        print "bulldProtocol: " + str(addr)
        print "buildProtocol: " + self.connectString

        p = self.protocol()
        p.factory = self
        return p

if __name__ == '__main__':


    def startUp():

        factory = ClusterClientFactory()
        factory.maxDelay = 120  #  two minutes

        factory.connectString = "FirstString..."
        reactor.connectTCP("localhost", 7300, factory)

        factory.connectString = "SecondString"
        reactor.connectTCP("localhost", 7300, factory)

    reactor.callWhenRunning(startUp)
    reactor.run()

----------------------------------

The results are that buildProtocol gets the second string both times.
startedConnecting gets the correct string, but all I have there is a
connection object.  I need the correct data in buildProtocol to do it this
way.

------------------------------------

C:\Users\Mark\src\play>python testclient.py
startFactory: FirstString...
Started connecting: <twisted.internet.tcp.Connector instance at 0x01DAB620>
FirstString...
Started connecting: <twisted.internet.tcp.Connector instance at 0x01E0EFD0>
SecondString
bulldProtocol: IPv4Address(TCP, '127.0.0.1', 7300)
buildProtocol: SecondString
Client Connected: SecondString
Welcome to SimpleServer5



bulldProtocol: IPv4Address(TCP, '127.0.0.1', 7300)
buildProtocol: SecondString
Client Connected: SecondString
Welcome to SimpleServer5

--------------------------


My "best" idea is to pass the strings to the factory in a dictionary indexed
by the IP address and the port.  Then, buildProtocol() can use that to
recover the string and I can use reactor.resolve() to translate the host
name to the IP address.  The real application won't have multiple
connections to the same host and port like this example, so this would work.

There MUST be a better way.  :-)

My "simpleserver" is below if you want to run this.

THANKS for all of your help.  I have the basic application running now
(including a Tkinter GUI  :-) ) and Twisted has saved me hundreds or even
thousands of lines of code...

Mark Bailey

------------------------------

from twisted.conch.telnet import StatefulTelnetProtocol
from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver

class TelnetEcho(StatefulTelnetProtocol):
    def connectionMade(self):
        self.factory.connection.append(self)
        self.sendLine("Welcome to SimpleServer5\r\n")


    def lineReceived(self, data):
        data = data.rstrip('\n\r')

        if data.upper() == 'BYE':
            self.sendLine("Goodbye...\r")
            self.transport.loseConnection()
        else:
            self.sendLine("Unrecognized command: %r\r" % (data,))

    def connectionLost(self, reason):
        self.factory.connection.remove(self)


class TelnetEchoFactory(protocol.Factory):
    protocol = TelnetEcho
    def __init__(self):
        self.connection = []


def createTelnetServer(port=7300):
    telnetinstance = TelnetEchoFactory()       #  needs to be a list
    reactor.listenTCP(port,telnetinstance)

if __name__ == "__main__":
    reactor.callWhenRunning(createTelnetServer)
    reactor.run()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20100210/acc93b9c/attachment.htm 


More information about the Twisted-Python mailing list