Getting started with WebSockets using Python and Tornado

Post to Twitter

Using WebSockets in Python with Tornado is very easy. Today I’ll show you how to build a very simple application that will demonstrate the basics of getting everything working.


Note: Make sure you are using a fairly new web browser, I tested this on the latest version of Firefox but Chrome and Safari should work as well. I’m using Python 2.7.4 but this should work on Python 3.x with little or no modifications. Finally, I’m doing this on Ubuntu 13 but this will work on OS X as well as other Linux distros. Modify as required.

Project Setup: I like to use Virtualenv to keep my global site-packages clean, this is typically how I work with any Python project. Feel free to set your project up as you see fit.

To get started create a new folder calling it whatever you wish. Inside of that folder add another folder called templates. In the root project folder create a file called ws_app.py and in the templates folder add a file called index.html.

Project Layout

Make sure you have Tornado installed, you can do this easily with the following command:

$ pip install tornado

The contents of index.html will look like the following:

<!DOCTYPE html>
<html>
<head>
    <title>Tornado WebSockets</title>
    <script>
        var ws;

        function onLoad() {
            ws = new WebSocket("ws://localhost:8080/websocket");

            ws.onmessage = function(e) {
               alert(e.data);
            };
        }

        function sendMsg() {
            ws.send(document.getElementById('msg').value);
        }
    </script>
</head>
<body onload="onLoad();">
    <strong>Message to Send:</strong>&nbsp;<input type="text" id="msg" maxlength="25" />
    &nbsp;<input type="button" onclick="sendMsg();" value="Send" />
</body>
</html>

As you can see this is nothing fancy and very minimal JavaScript – just enough to make this work. Essentially you can enter text and send it to the Tornado server and have that message sent back to you.

Lets take a look at the Python code in ws_app.py:

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop


class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        pass

    def on_message(self, message):
        self.write_message(u"Your message was: " + message)

    def on_close(self):
        pass


class IndexPageHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', IndexPageHandler),
            (r'/websocket', WebSocketHandler)
        ]

        settings = {
            'template_path': 'templates'
        }
        tornado.web.Application.__init__(self, handlers, **settings)


if __name__ == '__main__':
    ws_app = Application()
    server = tornado.httpserver.HTTPServer(ws_app)
    server.listen(8080)
    tornado.ioloop.IOLoop.instance().start()

You can see here I create a HTTPServer that listens on port 8080. The application sets up two handlers, one to serve the index.html page and one to handle the WebSocket traffic.

Start the application by running the following code:

$ python ws_app.py

You can then load the index.html page from here: http://localhost:8080

Running the application

This is obviously a very trivial application but will help you get started. Check out the excellent Tornado documentation on WebSockets to go further.

Post to Twitter

This entry was posted in JavaScript, Open Source, Python, Tornado. Bookmark the permalink.

6 Responses to Getting started with WebSockets using Python and Tornado

  1. Sean says:

    Great tutorial! This was my first foray into websockets and I liked how you stripped it down to the bare minimum.

    I can’t help thinking, though, for this particular use, why not just use XHR? I thought the only advantage of using a websocket is that it requires no request to be sent. If you’re sending a request to get a response, we already have things that can do that!

    I did some Googling and came across this article: http://www.peterbe.com/plog/are-websockets-faster-than-ajax, which concluded that there is a slight performance boost (less http overhead).

  2. Chad Lung says:

    @Sean,

    This article was only to show in simplest form how to get WebSockets and Tornado working together. I didn’t even use jQuery just to keep it as simple as possible.

    With AJAX, you have to poll for updates. With WebSockets the message can be sent immediately to the connected client(s). You can obviously run into latency and scaling issues with each so its going to depend on what your trying to accomplish and which is the best solution to pursue. This is where things like caching and load balancing start to become important as an application needs to scale.

    Chad

  3. Pingback: Using a Python client to test Tornado WebSockets | Giant Flying Saucer

  4. Taz El-Kikhia says:

    Good tutorial.

  5. dorothy says:

    Thank you for tutorial,it’s very useful for me . But I get some problem when I run python ws_app.py,nothing happend but start a new line .when I type http://localhost:8080 in the browser,it shows “Firefox can’t establish a connection to the server at localhost:8080.”,I guess the server isn’t started,but I don’t know how to figure it out.Could you give me some advices?

  6. Chad Lung says:

    @Dorothy,

    I’d suggest putting in some error handling in the __main__ section and printing out what the error is and why it’s not starting.

    Chad

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>