[Twisted-Python] Guidance on Proxy-type Application

Aaron Bush asb.bush at gmail.com
Thu May 28 13:22:20 MDT 2009


Thanks John.

Here is some sample code that is somewhat working for me right now.  Any and
all comments are greatly appreciated.

1) I setup a netcat listener on port 8080.
2) Start the twisted program, it connects to 8080 and then fires up a
listener on port 808 from the ChattyMCProtocol protocol.
3) Start a netcat client connection to the server process.
4) The client connection and any data they enter will be passed to the
'master control' process (ReconnectingClientFactory).

from twisted.internet.protocol import ReconnectingClientFactory,
ServerFactory
from twisted.protocols.basic import LineOnlyReceiver
from twisted.internet import reactor

"""Some test code using a chat-like approach with a master control node"""

class ChattyServerProtocol(LineOnlyReceiver):
    '''
    A test proto which will receive data and then forward it on the to the
master control
    '''
    delimiter = '\n'

    def connectionMade(self):
        self.transport.write("Welcome to the Server\n")
        """ Tell the master control that a client came in"""
        self.factory.parent.transport.write("Someone connected\n")

    def connectionLost(self, reason):
        self.factory.parent.transport.write("Server lost the connection to a
client")

    def lineReceived(self, line):
        print "Server got some data: " + line
        """ Now send the data to the master control"""
        self.factory.parent.transport.write("Client Said: %s\n" % line)


class ChattyServerFactory(ServerFactory):
    protocol = ChattyServerProtocol

    def __init__(self, parent):
        self.parent = parent
        pass

class ChattyMCProtocol(LineOnlyReceiver):
    delimiter = '\n'

    def __init__(self):
        """Connected so startup Server for clients"""
        self.server_factory = ChattyServerFactory(self)
        reactor.listenTCP(808, self.server_factory)

    def lineReceived(self, line):
        self.transport.write("Processing what you said: %s\n" % line)

class ChattyMCFactory(ReconnectingClientFactory):

    def startedConnecting(self, connector):
        print "Connecting..."

    def clientConnectionFailed(self, connector, reason):
        print "The connection failed"
        ReconnectingClientFactory.clientConnectionFailed(self, connector,
reason)

    def clientConnectionLost(self, connector, reason):
        print "The connection was lost"
        ReconnectingClientFactory.clientConnectionLost(self, connector,
reason)

    def buildProtocol(self, addr):
        print "Connected, reset the delay"
        self.resetDelay()
        # Next startup a server for the clients
        #self.server_factory = ChattyServerFactory(self)
        return ChattyMCProtocol()

reactor.connectTCP("127.0.0.1", 8080, ChattyMCFactory())
reactor.run()

Items that I don't know how to handle yet:
 - I need to determine how to better handle the case where the connection
made via ReconnectingClientFactory is dropped.  It does reconnect as the
Factory should but the problem is that the Server portion is not cleanly
shutdown so when the ChattyMCProtocol tries to listen it fails as the socket
is already in use.  Any ideas how to signal to the server to shutdown?
 - Much more to be done.  How to take this to the level of a proper Twisted
"application", etc.

Thanks,
-ab

On Thu, May 28, 2009 at 12:01 PM, John Santos <JOHN at egh.com> wrote:

>
> Hi Adam -
>
> I'm in pretty much the same situation as you and am working on a similar
> problem.  Very much a Python and Twisted newbie.
>
> The program I'm working on needs to talk to a variety of clients and to
> a single server, with more-or-less permanent connections to all of them.
>
> My problem is somewhat different from yours (and probably a little
> simpler), since all input from all clients goes to the server, and
> all output from the server goes to all clients (so I don't have to
> tag and remember which response goes to which client.)  However,
> there are other messages from the clients that don't go to the
> server, but instead do other things, some requiring responses.
> So the message handling in my program (what happens when dataRecieved
> gets called) may be more complicated than in yours.  But that is
> (at least from my perspective) the easy part.  Getting the twisted
> app to talk to the server and all the clients, and not to fall over
> dead when a client goes away, etc. is (to me) the hard part, and I
> feel like I've just gotten over a huge hump now that that is (mostly)
> working (as of two days ago.)
>
>
> I am using two factories, one to generate the object that talks to the
> server (using conch.telnet), and one to generate objects to talk to
> the clients.  The clients can come and go but would typically be
> permanent.  (Actually 3 factories right now, since I'm using the
> StdioProxyFactory from the example for debugging, but that will
> go away as I get the client protocol working.)
>
> I started from the dataforward.py example in Twisted book, but by
> now it has been massively changed.
>
> Before starting the reactor, I do a reactor.connectTCP to the server
> using the factory for the server connections and a reactor.listenTCP
> using the client connection factory, to listen for client connections.
>
> One change I had to make to the example was to promote the
> InputForwarder object from an attribute of the client connection
> object to a global object since it is common to all the
> client connections.  (I hope I have the terminology correct here;
> as I've said, I'm a Python newbie.)
>
> It turns out to be fairly small amount of code, and I think it
> can still be simplified some more.
>
> So I think you are on the right track.  HTH!
>
>
> --
> John Santos
> Evans Griffiths & Hart, Inc.
> 781-861-0670 ext 539
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20090528/8db3556e/attachment.html>


More information about the Twisted-Python mailing list