Network Programming with Twisted




(page 1)


Network Programming with Twisted




(page 2)


Introduction




(page 3)


Hello, World!



from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor

class Hello(Protocol):
def connectionMade(self):
self.transport.write("Hello, World!\n")
self.transport.loseConnection()

class HelloFactory(Factory):
protocol = Hello

if __name__ == '__main__':
reactor.listenTCP(9999, HelloFactory())
reactor.run()


(page 4)


Echo Server -- TCP



from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor

class Echo(Protocol):
def dataReceived(self, data):
self.transport.write(data)

class EchoFactory(Factory):
protocol = Echo

if __name__ == '__main__':
reactor.listenTCP(9999, EchoFactory())
reactor.run()


(page 5)


Echo Server -- UDP



from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class EchoUDP(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
self.transport.write(data, (host, port))

if __name__ == '__main__':
reactor.listenUDP(9999, EchoUDP())
reactor.run()



(page 6)


All of the above



from hello_serv import HelloFactory
from echo_serv_tcp import EchoFactory
from echo_serv_udp import EchoUDP
from twisted.internet import reactor

if __name__ == '__main__':
reactor.listenTCP(9001, HelloFactory())
reactor.listenTCP(9002, EchoFactory())
reactor.listenUDP(9002, EchoUDP())
reactor.run()


(page 7)


Protocols and Factories





(page 8)


The Reactor




(page 9)


Deferred Execution




(page 10)


Deferreds and deferToThread



from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor, threads

class QOTD(Protocol):
def connectionMade(self):
d = threads.deferToThread(getQuoteFromDB)
d.addCallback(self._cb)
d.addErrback(self._eb)

def _cb(self, quote):
self.transport.write(quote + '\n')
self.transport.loseConnection()

def _eb(self, error):
self.transport.write("Internal server error!")
self.transport.loseConnection()

(page 11)


Deferreds and deferToThread (cont'd)



def getQuoteFromDB():
# TODO: Connect to DB here
return 'I am a fish!'

class QOTDFactory(Factory):
protocol = QOTD

if __name__ == '__main__':
reactor.listenTCP(9999, QOTDFactory())
reactor.run()

(page 12)


LineReceiver




(page 13)


Echo client



from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor

class EchoClient(LineReceiver):
end="Bye-bye!"
def connectionMade(self):
self.sendLine("Hello, world!")
self.sendLine("What a fine day it is.")
self.sendLine(self.end)

def lineReceived(self, line):
print "receive:", line
if line==self.end:
self.transport.loseConnection()

(page 14)


Echo client (cont'd)



class EchoClientFactory(ClientFactory):
protocol = EchoClient

def clientConnectionFailed(self, connector, reason):
print 'connection failed:', reason.getErrorMessage()
reactor.stop()

def clientConnectionLost(self, connector, reason):
print 'connection lost:', reason.getErrorMessage()
reactor.stop()

factory = EchoClientFactory()
reactor.connectTCP('localhost', 8000, factory)
reactor.run()

(page 15)


XML-RPC server using Twisted Web


from twisted.web import server, xmlrpc

from twisted.internet import defer, reactor

class Echoer(xmlrpc.XMLRPC):

def xmlrpc_echo(self, *args):
"""Return all passed args."""
return args

def xmlrpc_hello(self):
"""Return 'hello, world'."""
return 'hello, world!'

(page 16)


XML-RPC (cont'd)



def xmlrpc_defer(self):
"""Show how xmlrpc methods can return Deferred."""
return defer.succeed("hello")

def xmlrpc_defer_fail(self):
"""Show how xmlrpc methods can return failed Deferred."""
return defer.fail(12)

def xmlrpc_fail(self):
"""Show how we can return a failure code."""
return xmlrpc.Fault(7, "Out of cheese.")

if __name__ == '__main__':
resource = Echoer()
reactor.listenTCP(7080, server.Site(resource))
reactor.run()

(page 17)


A simple web server



from twisted.web import server, static
from twisted.internet import reactor

root = static.Data("hello world", "text/plain")
root.putChild('', root)

site = server.Site(root)
reactor.listenTCP(10998, site)
reactor.run()

(page 18)


Simple PB server



from twisted.spread import pb
from twisted.internet import app
from twisted.cred.authorizer import DefaultAuthorizer

class DefinedError(pb.Error):
pass

class SimplePerspective(pb.Perspective):
def perspective_echo(self, text):
print 'echoing',text
return text
def perspective_error(self):
raise DefinedError("exception!")


(page 19)


Simple PB server (cont'd)



class SimpleService(pb.Service):
def getPerspectiveNamed(self, name):
p = SimplePerspective(name)
p.setService(self)
return p

if __name__ == '__main__':
appl = app.Application("pbecho")
auth = DefaultAuthorizer(appl)
service = SimpleService("pbecho", appl, auth)
service.getPerspectiveNamed("guest").makeIdentity("guest")
appl.listenTCP(pb.portno, pb.BrokerFactory(pb.AuthRoot(auth)))
appl.run(save=0)

(page 20)


Simple PB client



from twisted.internet import reactor
from twisted.spread import pb

from pbecho import DefinedError

def success(message):
print "Message received:",message
# reactor.stop()

def failure(error):
t = error.trap(DefinedError)
print "error received:", t
reactor.stop()

(page 21)


Simple PB client (cont'd)



def connected(perspective):
d = perspective.callRemote('echo', "hello world")
d.addCallbacks(success, failure)
perspective.callRemote('error').addCallbacks(success, failure)
print "connected."

pb.connect("localhost", pb.portno,
"guest", "guest",
"pbecho", "guest", 30).addCallbacks(connected, failure)

reactor.run()

(page 22)


Referenceable, Copyable, Cacheable, oh my!




(page 23)


Questions?



(page 24)