Getting started with Websockets

Websockets were standardized back in 2011 (RFC 6455). Since then support has been added to most major browsers.

Background

Websockets allow full duplex communication between a browser and a server. This is particularly useful for applications which need to frequently send and receive small messages because it avoids HTTP overhead.

In Javascript, new Websocket connections are made with code similar to the following:

var ws = new WebSocket('ws://example.com/socket')

When a connection is established the client will send a request with an HTTP/1.1 upgrade header similar to the following:

GET /socket HTTP/1.1
Host: example.com
Upgrade: websocket
Origin: http://example.com
Connection: keep-alive, Upgrade
Sec-WebSocket-Key: PdspSkfns9qGxGTNajm+Tw==
Sec-WebSocket-Version: 13

If the server supports Websockets, it will reply with a message similar to the following:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: eO+uwdEEfbO7q68DAzeDjM4Gs8c=

From this point on, the connection will look more like a standard TCP connection. As well as not requiring any HTTP headers for subsequent messages, messages can be sent by either the client or the server (bidirectional) and messages can be sent at the same time (full-duplex).

Setting up a server

There is a pretty wide range of libraries which can be used to implement a Websocket server. This post is going to use the Tornado Python web framework. On CentOS 7 it can either be installed with yum:

yum install -y python-tornado

Alternatively if you need a more up-to-date version, it can be installed using pip:

pip install tornado

Once Tornado is installed, a very simple Websocket application could look something like the following:

#!/usr/bin/env python

"""A simple Websocket server which just echos messages"""

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

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    """ A very simple websocket handler"""
    def on_message(self, message):
        """Echo message back to the client"""
        self.write_message('server: %s' % message)

if __name__ == '__main__':
    APP = tornado.web.Application([(r'/socket', EchoWebSocket)])
    APP.listen(8888)
    tornado.ioloop.IOLoop.instance().start(

In the code above the key method is the on_message method. This is called every time a client sends a new message and replies with the clients message prefixed withserver:. Starting the server is just a case of running the script with Python:

$ python websocket_echo_server.py

Note: unlike other Python web frameworks, Tornado isn't normally use with a WSGI server, however this is possible. For more info, refer to the Tornado deployment docs.

Connecting to a Websocket

Once the Websocket server is up and running Javascript similar to the following can be used to connect to the server:

var ws = new WebSocket('ws://localhost:8888/socket');

A call-back function can then be defined to handle messages:

ws.onmessage = function(evt){
  console.log(evt.data);
};

And finally a test message can be sent to the server:

ws.send("Hello world");

If everything works as expected, the server should reply with server: Hello world, which should be logged to the console. Normally the Javascript above would be included in a web page, however a quick way to test the code is to open the Firefox Web Console ( ctrl + shift + k ) and type directly into the console:

A screenshot showing the Firefox Web Console being used to connect to a
  Websocket.