Why HTTP is not enough for realtime apps
The web was built around HTTP's request/response model: a client loads a page, and nothing happens until the user triggers another request. AJAX made pages feel more dynamic around 2005, but communication was still client-driven, requiring user interaction or periodic polling to pick up new server data.
Techniques for letting the server initiate communication have existed for a long time under names like "Push" or "Comet." The most common hack is long polling, where the client opens an HTTP connection that the server keeps hanging until it has data to send back. Other approaches include Flash sockets, XHR multipart requests, and htmlfiles. These work — they power applications like Gmail chat — but they all carry HTTP overhead that makes them poorly suited to low latency use cases such as multiplayer browser games or any realtime component.
Opening a WebSocket connection
The WebSocket API creates a persistent "socket" connection between a browser and a server, where either side can start sending data at any time. Opening a connection is a simple constructor call:
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
Note the ws: URL scheme for WebSocket connections. There is also wss:, used for secure WebSocket connections the same way https: secures HTTP.
Event handlers on the connection tell you when it opens, when messages arrive, or when an error occurs. The constructor's second argument accepts optional sub-protocols as a string or an array of strings; the server accepts one of the passed sub-protocols, and you can check which one via the protocol property. Sub-protocol names must be registered in the IANA registry — as of February 2012, only soap was registered.
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
Sending and receiving messages
Once the connection is open, the send('your message') method sends data to the server. The spec originally supported only strings; the latest version also allows binary messages as Blob or ArrayBuffer objects.
// Sending String
connection.send('your message');
// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);
// Sending file as Blob
var file = document.querySelector('input[type="file"]').files[0];
connection.send(file);
Incoming messages fire the onmessage callback, with the payload in the event's data property. Binary frames can be received in Blob or ArrayBuffer format; set the binaryType property of the WebSocket object to 'blob' or 'arraybuffer' to choose. The default is 'blob'. The binaryType setting does not need to match what you send.
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};
WebSocket extensions, another recent addition, enable features such as per-frame compression and multiplexing. After the open event, the server-accepted extensions are available in the extensions property. No official extensions spec had been published as of February 2012.
// Determining accepted extensions
console.log(connection.extensions);
Cross-origin and proxy considerations
Cross-origin communication is built into the protocol. Clients on any domain can connect, and the server decides whether to serve all clients or only those from specific domains. You should still only communicate with parties you trust.
The protocol's main compatibility problem is proxy servers. WebSocket relies on the HTTP upgrade system (normally used for HTTP/SSL) to upgrade an HTTP connection to a WebSocket connection, and some proxies drop such connections. A client may support WebSocket yet still fail to connect through a company network's proxy.
Using WebSocket without waiting for full browser support
WebSocket is not fully implemented in all browsers, but fallback libraries make it usable today. socket.io is a popular option, providing both client and server implementations with fallbacks when WebSocket is unavailable — although, as of February 2012, it did not yet support binary messaging. Commercial services like PusherApp also exist, exposing an HTTP API that sends WebSocket messages to clients from any web environment, at the cost of extra overhead from the HTTP request.
What happens on the server
WebSocket changes the server-side usage pattern. Traditional stacks like LAMP, built around HTTP's request/response cycle, generally do not handle large numbers of open connections well. Keeping many connections open simultaneously requires an architecture that sustains high concurrency at low performance cost, typically via threading or non-blocking I/O.
Implementation options
- Node.js: Socket.IO, WebSocket-Node, ws
- Java: Jetty
- Ruby: EventMachine
- Python: pywebsocket, Tornado
- Erlang: Shirasu
- C++: libwebsockets
- .NET: SuperWebSocket
Protocol status
The wire protocol — handshake and data transfer — is now defined as RFC6455. Late Chrome and Chrome for Android builds are fully compatible with RFC6455, including binary messaging; Firefox gained compatibility in version 11 and Internet Explorer in version 10. Older protocol versions still work but are known to be vulnerable and should be replaced with the latest version on any server implementation.
Where WebSocket fits
Use WebSocket when you need genuinely low-latency, near-realtime client-server communication. That may require rethinking the server side, with new focus on technologies such as event queues. Representative use cases include:
- Multiplayer online games
- Chat applications
- Live sports tickers
- Realtime updating social streams



