Null Disquisition

Lots of talk about nothing

« Back to blog

WebSockets in Python

Since the dawn of AJAX, web developers have longed for persistent server-side connections. For a while Comet was hailed as the bastion of “server push”, but deep down we knew it was just a hack. Now finally, years later, we have an API and a protocol being standardized for socket connections between the browser and the server – aptly named, WebSockets.

WebSockets are bi-directional communication channels that run on single TCP sockets allowing communication between the client and the server. Since they behave like regular INET sockets, we should be able to easily implement them with existing tools. However, when I was looking for example implementations in Python, I didn’t find anything that quite satisfied me.

Python sockets module

Now don’t make the mistake of thinking I’m a systems programmer. I have never written a low-level network application like this, and in fact this is my first time playing with sockets or select in Python. The root of all of this is the WebSocket itself, which is just a socket.

import socket
websocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
websocket.bind(("localhost", 9999))
websocket.listen(5)

That’s all you need to get the WebSocket up and running. Granted, it’s not very useful since you can’t connect to it (no handshake), but it’s a WebSocket nonetheless. When a client connects to the socket, it initiates the handshake with the following

GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:9999
Origin: file://
Sec-WebSocket-Key1: x   d3L703 2  {63 k  L1( 90
Sec-WebSocket-Key2: ^    14   +40Z7R<12om I8  0[

??????????????

And expects a response in a similar form:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: file://
WebSocket-Location: ws://localhost:9999/
Sec-Websocket-Origin: file://
Sec-Websocket-Location: ws://localhost:9999/

??????????????

The “?” are random bits used in the challenge/response part of the handshake. Interesting note: In addition to failing to do the Challenge/Response, Chrome looks for the “Websocket-X” headers, while Safari (correctly) looks for the “Sec-Websocket-X” headers.

Here’s my full standalone WebSocket server: http://gist.github.com/512987

I won’t delve into the details of the implementation, namely because I’m sure it’s suboptimal. I was pretty happy with Challenge/Response piece. I read the spec from IETF and implemented it, nice and simple. Aren’t open standards great? I ended up having to do the handshake because Safari 5 won’t let you use a WebSocket otherwise.

Stay tuned for everyone’s favorite asynchronous demo: a chat program!

-David