Wednesday, October 6, 2010

Learning Twisted (part 7) : Understanding protocol class implementation

In my last post, I had focused on protocol factory class, various methods it needs to provide and also the code flow within which these methods gets called or invoked.
Here we will look into the structure of protocol class , various methods it needs to provide and context in which they are called.

There are two ways to lookup and learn this:

  • Look at the interface definition: IProtocol(Interface) in interfaces.py
  • Like I did in my previous posting , supply a protocol class with no methods and look at the traceback to understand the code flow

So usual imports for writing a custom protocol:

from twisted.web import proxy
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.python import log
import sys
log.startLogging(sys.stdout)

It is much better to derive from protocol.Protocol to build custom protocol. It does a few things for you.
Any intricate logic should be built using the connect, disconnect, data received event handlers and methods to write data onto connection
makeConnection method sets the transport attribute and also calls connectionMade method . You can use this to start communicating once the connection setup has been established.
dataReceived method is called when there is data to be read off the connection. connectionLost is called when the transport connection is lost for some reason. To write data on the connection, you use the transport method self.transport.write. This results in adding the data to buffer which will be sent across the connection. To make twisted send the data or buffer immediately, you can call self.transport.doWrite


class MyProtocol(protocol.Protocol):
    
    #def makeConnection(self, transport):
    #    print transport       
        
    def connectionLost(self, reason):
        print reason
        
        
    def connectionMade(self):
        print "connection made"
        print self.transport
        self.transport.writeSomeData("www")
        
    def dataReceived(self, data):
        print data

Following is a remnant of previous post on protocol factory. It illustrates, how some of the events are communicated upwards. buildProtocol is called to create a protocol instance and associate it with a connection. Other events like connection lost or failed to connect are communicated vi event handlers like clientConnectionLost, clientConnectionFailed. Other methods should be self descriptive like startedConnecting, which is called before the connection is made.

class myProtocolFactory():
    protocol = MyProtocol
    
    def doStart(self):
        pass
        
    def startedConnecting(self, connectorInstance):
        print connectorInstance
        
    def buildProtocol(self, address):
        print address
        return self.protocol()
        
    def clientConnectionLost(self, connection, reason):
        print reason
        print connection
        
    def clientConnectionFailed(self, connection, reason):
        print connection
        print reason
        
    def doStop(self):
        pass

It is much better to use client factory or reconnecting client factory for most purposes.

from twisted.internet.protocol import ClientFactory, ReconnectingClientFactory

class myProtocolFactory(ReconnectingClientFactory):
    protocol = MyProtocol
    
    def startedConnecting(self, connector):
        print 'Started to connect.'
        
    def buildProtocol(self, address):
        print address
        return self.protocol()
Finally, we need a connector to tie up all these concepts of factory, protocol, connection(transport).
reactor.connectTCP('localhost', 50000, myProtocolFactory())
reactor.run()

No comments:

Post a Comment