Saltycrane logo

SaltyCrane Blog

Notes on Python, Django, and web development on Ubuntu Linux

    

Quick notes on trying the Twisted websocket branch example

Here are my quick notes on trying out the websocket example in Twisted's websocket branch. The documentation is here. The Twisted ticket is here. This came about after some conversation with @clemesha on Twitter.

(A Web Socket is a new, still-in-development technology, introduced in HTML5, and may be used for real-time web applications. It provides a simple (maybe better) alternative to existing Comet technology.)

(Note: The WebSocket API is still changing. Google Chrome supports (a version of) it. Firefox as of version 3.6, does not support it yet.)

(I am no expert on Web Sockets. I just think they are cool and want to start using them.)

Install Twisted websocket branch

  • Install pip and virtualenv
  • Install the Twisted websocket branch in a virtualenv
    $ cd ~/lib/python-environments
    $ virtualenv --no-site-packages --distribute twisted-websocket-branch
    $ pip install -E twisted-websocket-branch/ -e svn+svn://svn.twistedmatrix.com/svn/Twisted/branches/websocket-4173-2
    

~/wsdemo/index.html

<html>
  <head>
    <title>WebSocket example: echo service</title>
  </head>
  <body>
    <h1>WebSocket example: echo service</h1>
    <script type="text/javascript">
        var ws = new WebSocket("ws://127.0.0.1:8080/ws/echo");
        ws.onmessage = function(evt) {
            var data = evt.data;
            var target = document.getElementById("received");
            target.value = target.value + data;
        };
        window.send_data = function() {
            ws.send(document.getElementById("send_input").value);
        };
    </script>
    <form>
      <label for="send_input">Text to send</label>
      <input type="text" name="send_input" id="send_input"/>
      <input type="submit" name="send_submit" id="send_submit" value="Send"
             onclick="send_data(); return false"/>
      <br>
      <label for="received">Received text</label>
      <textarea name="received" id="received"></textarea>
    </form>
  </body>
</html>

~/wsdemo/demo.py

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


class Echohandler(WebSocketHandler):
    def frameReceived(self, frame):
        log.msg("Received frame '%s'" % frame)
        self.transport.write(frame + "\n")


def main():
    log.startLogging(sys.stdout)
    root = File(".")
    site = WebSocketSite(root)
    site.addHandler("/ws/echo", Echohandler)
    reactor.listenTCP(8080, site)
    reactor.run()


if __name__ == "__main__":
    main()

Try it

  • Activate virtualenv
    $ source ~/lib/python-environments/twisted-websocket-branch/bin/activate
    
  • Run server
    $ cd ~/wsdemo
    $ python demo.py
    
  • Visit http://localhost:8080/ in your WebSocket-enabled browser (e.g. Google Chrome)
  • Here's the console output:
    2010-05-25 21:47:46-0700 [-] Log opened.
    2010-05-25 21:47:46-0700 [-] twisted.web.websocket.WebSocketSite starting on 8080
    2010-05-25 21:47:46-0700 [-] Starting factory <twisted.web.websocket.WebSocketSite instance at 0x94243ac>
    2010-05-25 21:47:56-0700 [HTTPChannel,0,127.0.0.1] 127.0.0.1 - - [26/May/2010:04:47:56 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.9 Safari/533.2"
    2010-05-25 21:47:56-0700 [HTTPChannel,1,127.0.0.1] 127.0.0.1 - - [26/May/2010:04:47:56 +0000] "GET /favicon.ico HTTP/1.1" 404 145 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.9 Safari/533.2"
    2010-05-25 21:48:16-0700 [HTTPChannel,2,127.0.0.1] Received frame 'hello'
    2010-05-25 21:48:25-0700 [HTTPChannel,2,127.0.0.1] Received frame 'Twisted+Websocket!'

See also

4 Comments — feed icon Comments feed for this post


#1 Asbjørn Andersen commented on 2010-05-26:

Hi,

websockets are awesome! I wanted to expand this to send messages to all transports ( connected clients ). I simply made a transport array ( appending on connectionMade and removing on connectionLost ), and sendt to all available transports for every sendMessage.

It works, but I'm wondering if its a good way to go about doing that? I haven't used twisted a lot before, so there might be something I missed ;)

//asbjorn


#2 Eliot commented on 2010-05-26:

Hi Asbjørn, I'd like to do this also-- care to share a code snippet? (Sorry I don't know if there is a better way.)


#3 Asbjørn Andersen commented on 2010-05-26:

Sure,

http://pastebin.com/9GtcitDd

Thats with rushman's tx-websockets as base ( http://bitbucket.org/rushman/tx-websockets/src ). Thats not exactly equivalent to what you've got, but hopefully you'll get the idea :P I guess you have to extend init and connectionLost in addition to updating your frameReceived...? Something like that.

Let me know if you get it working and/or make some new discoveries :)

//asbjornenge


#4 Eliot commented on 2010-05-26:

Asbjørn, Thanks for the code! Ok, so you started with tx-websockets... I had initially thought this Twisted branch was the best option, but I may need to relook at alternatives. Thanks again. I'll add updates if I make any progress. Let me know also if you have any new info.

Post a comment

Required
Required, but not displayed
Optional

Format using Markdown. (No HTML.)
  • Code blocks: prefix each line by at least 4 spaces or 1 tab (and a blank line before and after)
  • Code span: surround with backticks
  • Blockquotes: prefix lines to be quoted with >
  • Links: <URL>
  • Links w/ description: [description](URL)
Created with Django | Hosted by Linode