Search code examples
pythontwistedtwisted.webtwisted.internet

Controlling Twisted based server from a web interface?


I created a server with a custom protocol using Twisted and I have clients that connect to the server on a specific port (say port 1234). I am looking to create a control interface for the server based on a web page of some sort. My research so far indicated Nevow is popular choice but I only need something very simple.

Say for example, every time a browser accesses the hello world page on port 8080, I send a message to clients connected on 1234.

I am a bit confused as to how I can connect these 2 together. I assume I would need to call Server.message from HelloResource.render_GET ?

from twisted.internet import protocol, reactor
from twisted.web.resource import Resource

    class Server(protocol.Protocol):
        def dataReceived(self, data):
            #do something on the server side

        def message(self)
            #send message to clients

    class HelloResource(Resource):
        isLeaf = True

        def render_GET(self,request):
            return "<html>Hello, world!</html>"

factory = protocol.Factory()
factory.protocol = Server
reactor.listenTCP(1234, factory)

reactor.listenTCP(8080, server.Site(HelloResource()))

reactor.run()

Solution

  • If you want to do things this way, your Server.message obviously has to be a @classmethod, and it has to have access to a list of clients, and send the message to each of them.

    Something like this:

    class Server(protocol.Protocol):
        clients = set()
    
        def dataReceived(self, data):
            #do something on the server side
            pass
    
        def connectionMade(self):
            Server.clients.add(self)
    
        def connectionLost(self):
            Server.clients.remove(self)
    
        @classmethod
        def message(cls):
            for client in cls.clients:
                client.transport.write('got GET request\n')
    

    Now you can just call Server.message() from your render_GET method.

    I'm not sure this is the best design—really, there are all kinds of better objects to hang a list of clients on than the protocol class—but it should work.