Using the WebSocket protocol with Twisted

Introduction

The WebSocket protocol is a protocol introduced in HTML5, intended to replace Comet and other long-polling solutions, to provide a rich communication mechanism over HTTP. See the specification for more information about the protocol itself. websocket implements the server side of the WebSocket protocol.

Using WebSocketSite

WebSocketSite is a Site class handling the WebSocket handshake and dispatching request to WebSocketHandler instances. Like other site instances, it can serve any normal HTTP requests, rendering WebSocket if the Connection: Upgrade header has been sent. The following example creates a file listing server, with echo being registered as a WebSocket resource.

from twisted.internet import reactor
from twisted.web.websocket import WebSocketHandler, WebSocketSite
from twisted.web.static import File


class Echohandler(WebSocketHandler):

    def frameReceived(self, frame):
        self.transport.write(frame)


if __name__ == "__main__":
    root = File(".")
    site = WebSocketSite(root)
    site.addHandler("/echo", Echohandler)
    reactor.listenTCP(8080, site)
    reactor.run()

Using WebSocketHandler

WebSocketHandler provides basic facility to help you write a WebSocket resource handler. The frameReceived method will be called with every frame sent by the client. The transport object can be used to send data back to the client, using the write, or closing the connection, using the close method. The connectionLost callback will be called when the connection is closed. The following example shows the usage of those different APIs.

from twisted.web.websocket import WebSocketHandler
from twisted.python import log


class ExampleWebSocketHandler(WebSocketHandler):

    def __init__(self, transport):
        WebSocketHandler.__init__(self, transport)
        self.counter = 0
        self.transport.write("hello world")

    def frameReceived(self, frame):
        self.counter += 1
        if self.counter == 10:
            self.transport.write("Enough play")
            self.transport.close()
        elif self.counter % 2:
            self.transport.write("Now we're even")
        else:
            self.transport.write("That was odd")

    def connectionLost(self, reason):
        log.msg("Connection closed after %d frames" % self.counter)

Notes

The WebSocket specification specifies that frames must be encoded in UTF-8, but the implementation in Twisted doesn't make any check. Your application code must ensure that it only sends frames correctly encoded in UTF-8, and possibly be able to handle frames sent by the client which are not correctly encoded.