Managing Multiple Services

Table of contents:

One of the most powerful features of Twisted is its ability to run multiple services in a single process. You can write an application that shares objects and data with many different protocols at the same time. You can also manage the different services in an application at runtime, starting and stopping them individually without having to restart your application.

11.3.1. How Do I Do That?

Add more than one service to an application object and run the application using twistd. You can iterate through the current services in your application by wrapping the application object in the service.IServiceCollection interface. Call startService and stopService to start or stop one of the services. Example 11-4 creates an application that offers both web and Telnet interfaces to the same data, and a web administration interface that lets you selectively start and stop services.

Example 11-4. multiservice.py


from twisted.application import service, internet

from twisted.internet import protocol, reactor, defer

from twisted.protocols import basic

from twisted.web import resource, server as webserver



class Reverser:

 def _ _init_ _(self):

 self.history = []



 def reverse(self, string):

 self.history.append(string)

 reversed = string[::-1]

 return reversed



class ReverserLineProtocol(basic.LineReceiver):

 def lineReceived(self, line):

 if hasattr(self, 'handle_' + line):

 getattr(self, 'handle_' + line)( )

 else:

 self.sendLine(self.factory.reverser.reverse(line))



 def handle_quit(self):

 self.transport.loseConnection( )



class ReverserLineFactory(protocol.ServerFactory):

 protocol = ReverserLineProtocol



 def _ _init_ _(self, reverser):

 self.reverser = reverser



class ReverserPage(resource.Resource):

 def _ _init_ _(self, reverser):

 self.reverser = reverser



 def render(self, request):

 if request.args.has_key("string"):

 string = request.args["string"][0]

 reversed = self.reverser.reverse(string)

 else:

 reversed = ""



 return """

 

Previous Strings

  • %s

""" % (reversed, " ".join(["

  • %s
  • " % s for s in self.reverser.history])) class ServiceAdminResource(resource.Resource): def _ _init_ _(self, app): self.app = app def render_GET(self, request): request.write("""

    Run multiservice.py using twistd. It will start a server that offers two different interfaces to a Reverser object, which reverses strings. You can connect to the server using telnet on port 2323:

    
     $ telnet localhost 2323
    
     Trying 127.0.0.1...
    
     Connected to sparky.
    
     Escape character is '^]'.
    
     this is a test
    
     tset a si siht
    
     another test
    
     tset rehtona
    
     quit
    
     Connection closed by foreign host.
    
    
     

    You can also access the server using a web browser on port 8000. Figure 11-1 shows how the history data is shared between the Telnet service and the web service.

    Figure 11-1. The multiservice.py web interface

     

    Example 11-4 also runs a second web server on port 8001. This server provides the interface shown in Figure 11-2 for starting and stopping services.

    Now, if you try to telnet to port 2323, you find that the service is no longer available:

    
     $ telnet localhost 2323
    
     Trying 127.0.0.1...
    
     telnet: Unable to connect to remote host: Connection refused
    
    
     

    Figure 11-2. Stopping the Telnet service through the web administration interface

     

    11.3.2. How Does That Work?

    Example 11-4 creates three Resource objects: lineService, webService, and webAdminService. It uses setServiceParent to register each of them as a child of application. The ReverserLineFactory used by lineService is initialized with a Reverser object; this same object is passed to the ReverserPage that webService uses to handle web requests. Since both services are using the same object, they're able to transparently share data.

    The webAdminService in Example 11-4 uses a ServiceAdminPage object to provide a web interface for starting and stopping resources. ServiceAdminPage is initialized with the application object so that it can access all available services. As a twisted.python.components.Componentized object, there's not much you can do with the application directly. Instead, you expose one of its internal objects by wrapping it in the interface you want to use. To loop through all the services, the ServiceAdminPage class uses the service.IServiceCollection interface, which returns an iterable object. ServiceAdminPage renders a form with an input checkbox for each service. When you submit this form, ServiceAdminPage loops through the services again and compares their current state with the checkbox value. If the service is running, but the box wasn't checked, it stops the service; if the service wasn't running, but the box was checked, it starts the service.

    The web administration service in Example 11-4 even lets you stop it. That's probably not something you want to allow in a real application!


Getting Started

Building Simple Clients and Servers

Web Clients

Web Servers

Web Services and RPC

Authentication

Mail Clients

Mail Servers

NNTP Clients and Servers

SSH

Services, Processes, and Logging



Twisted Network Programming Essentials
Twisted Network Programming Essentials
ISBN: 0596100329
EAN: 2147483647
Year: 2004
Pages: 107
Authors: Abe Fettig

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net