Mike Taylor Bruce Lawson by Mike Taylor, Bruce Lawson in Articles

Article tags:

This article is licensed under a Creative Commons Attribution, Non Commercial — ShareAlike 3.0 Unported license.

Introducing Web Sockets

Introduction

Opera 11 and above support Web Sockets, a feature once part of the HTML5 spec known as TCPConnection. Web Sockets today, however, are specified in two places: the Web Sockets API is maintained by HTML5 editor Ian Hickson, while the Web Socket protocol is edited by Ian Fette. Web Sockets allow an application to push information back and forth between server and browser, rather than having to poll the server at set intervals or use <iframe> tricks — this allows web developers to cut down on unnecessary HTTP traffic, hacks and complexity.

In this article we will explain the background to Web Sockets, show why it is a cool feature, and give you some simple usage examples to get you up to speed.

Web Sockets history

Urban legend has it that Web Sockets were invented by Ian Hickson as a way to control his model train set from a browser. Unfortunately, it's not true — Hickson says on the matter (personal communication):

I think work on Web Sockets (TCPConnection at the time) predates my thoughts of running my train layout using Web Sockets, but Web Sockets definitely would make doing so much easier. The problem is the normal Web app controlling a single system problem: there is one computer with a serial port connection to the Märklin Interface unit, and one wants to be able to write a Web page that communicates with that computer, sending instructions and receiving updates, without having to poll, have multiple connections, use <script> streams in <iframe>s, etc.

Why Web Sockets are cool

The Web Sockets API allows you to open a connection to a server using the new ws protocol, which remains open for the life of that session. It's full-duplex, that is, it allows communication in both directions simultaneously. It also has much less overhead than repeatedly polling a server to see if anything has changed. Previously, such functionality was only available using plugin technologies such as Flash.

In tests run by Kaazing Corp, who have been closely involved in the specification process, it was found that "HTML5 Web Sockets can provide a 500:1 or — depending on the size of the HTTP headers — even a 1000:1 reduction in unnecessary HTTP header traffic and 3:1 reduction in latency";.

In short: Web Sockets can make your applications faster, more efficient, and more scalable.

How Web Sockets works

Web Sockets comprises a JavaScript API, described below, and the protocol ws: — or wss: for encrypted transmission. Opera supports version -00 of the protocol (aka -76). This is the same as Chrome 6, Safari 5.0.2 and Firefox 4 beta. The protocol is standardised by the IETF and is liable to change; the API is unlikely to change however. This means that your application might stop working if it's talking to a server that uses a different version of the protocol, but with a relatively stable client-side API you probably won't have to change your client-side code.

The Web Sockets API

To connect to a Web Socket server, you use the WebSocket constructor like so:

var ws = new WebSocket('ws://example.org:12345/demo');

You can also request specific subprotocols with a second parameter:

var ws = new WebSocket('ws://example.org:12345/demo', 'my-chat-protocol');

If you require more than one subprotocol, you can pass them in as an array of strings (to be supported in a future version of Opera):

var ws = new WebSocket('ws://example.org:12345/demo', ['chat-protocol-v2-with-bells-and-whistles', 'chat-protocol']);

The server will choose the most compatible version, which can then be checked by reading the ws.protocol property.

You can try to connect to any host and any port except blocked ports, however the server needs to support Web Sockets and will expect a connection from the designated page that is expected to open the connection for it to be established. A subprotocol, if used, is an arbitrary string (composed of printable ASCII characters) that ensures that the client and server send messages that are mutually comprehensible. For example, Caucho Technology writes that subprotocols are useful to make sure a Quake/2.0 [WebSocket] client won't get confused talking to a Quake/1.0 [WebSocket] server.

If the connection is established, the WebSocket object receives an open event, at which point you can start to send and receive messages. In the context of Web Sockets, a message is simply a string of text, for example, a bit of JSON. You send a message using the send() method, and you handle incoming messages with an onmessage event listener:

ws.onopen = function(e) {
  // the connection is now established
  // let's send a simple message
  this.send('{"username": "Bruce", "message": "Hello!"}');
}

ws.onmessage = function(e) {
  // got a message from the server
  var msg = JSON.parse(e.data);
  alert(msg.message);
}

If the server refuses the connection, or if the connection closes for some reason, the WebSocket object receives a close event.

ws.onclose = function(e) {
  alert('WebSocket closed :-(');
}

You can close the connection with the close() method:

ws.close();

If the server sends frames that the browser doesn't understand (maybe because the server only supports a newer version of the protocol), then you will get error events. If you get error events but no message events, you may want to close the connection and fall back to using something else, such as, XHR long-polling or a Comet server.

Feature detection of Web Sockets is simple — just do the following:

if ('WebSocket' in window) {
  // Web Sockets supported
} else {
  // Web Sockets not supported
}

Or if you're already using Modernizr in your application, detection is just as simple:

if (Modernizr.websockets) {
  // Web Sockets supported
} else {
  // Web Sockets not supported
}

What about non-supporting browsers?

The HTML5 Cross browser Polyfills wiki lists three scripts that you can use as shims to simulate Web Sockets for older, non-supporting browsers (note that we haven't tested all of them). The Socket.IO project is a particularly nice solution as it bundles a Node.js Web Socket server with a unified, abstracted API with automatic fallbacks to Flash sockets, AJAX long polling, AJAX multipart streaming, <iframe> streaming and JSONP for less-capable clients. Socket.IO is open-source and works with Node.js, with a few other compatible implementations for other server technologies.

Demos

The following applications take advantage of Web Sockets to provide (near) real-time multi-user interactions:

  • Mr. Doob's Multiuser Sketchpad: In this multi-user <canvas> drawing application, Web Sockets are used to to pass along the coordinates of the lines that other users draw back to each client as they happen.
  • Rumpetroll: As a tadpole, you can swim around and chat with other tadpoles. Web Sockets allow for the locations of tadpoles and messages to be passed along to each user.
  • wordsquared.com: In this massively multiplayer online word game, Web Sockets are used to allow users to see everybody else's tiles as they are played.

In addition to those demos, Ericsson Labs has a nice screencast demonstrating the benefits of Web Sockets over HTTP long-polling for real-time applications:

Resources