Introduction to WebSocket

Both Orbiter (Union's JavaScript framework) and OrbiterMicro (a lightweight configuration of Orbiter) include native support for WebSocket. In browser-based applications, WebSocket speeds up network communications and reduces bandwidth consumption.

The following live demo shows the dramatic difference between WebSocket and traditional AJAX/XMLHTTPRequest communications. The left side shows an application's ping over traditional HTTP, using Comet-style long-polling. The right side shows the same application's ping over WebSocket. The ping over WebSocket is about twice as fast as the ping over HTTP.

This document explains how WebSocket communications work, how WebSocket benefits networked applications, and how to use WebSocket with Union Platform.


WebSocket is enabled by default in Union, so JavaScript applications connected to Union Server higher will automatically use WebSocket in browsers that support it. No special code is required to use WebSocket with Union. Simply building your application with Orbiter or OrbiterMicro will enable WebSocket communications.


What is WebSocket?

WebSocket is a network technology for conducting two-way communications between a client (typically a web browser) and a server over a persistent TCP/IP socket. Using JavaScript in a web browser that supports WebSocket, a web page can open a long-lasting connection to a server, and then send and receive arbitrary data over that connection. For example, a stock-ticker application could use WebSocket to send a constant stream of stock updates to a web page. Or an action game could use WebSocket to transmit data between a game server and a group of connected players.

Why Should I Use WebSocket?

WebSocket was created to address shortcomings in HTTP's communications architecture, which was not originally designed for use with real-time networked applications such as action games, chat, collaborative document editing, and data feeds.

If you are creating a web-based JavaScript application that regularly sends information to, or retrieves updates from, a server then you can use WebSocket to speed up your application's network communications and to reduce the amount of bandwidth your application uses. If, on the other hand, you are simply creating a static web page that loads once and has no further need to contact the server, then you don't need WebSocket at all; standard HTTP communications are perfectly suited to serving static web pages.

How Does WebSocket Work?

Here's the general flow of client/server communications over WebSocket:

  1. A web browser (or other client) opens a persistent TCP/IP socket to a given domain on a given port, typically port 80.
  2. The web browser sends a "hello" message to the server introducing itself and asking to begin a persistent WebSocket connection.
  3. The server responds by sending its a "hello" message back to the web browser. The server's "hello" message includes a security-challenge response.
  4. If the server's security-challenge response is deemed valid by the web browser, the persistent WebSocket connection is established.
  5. Once the WebSocket connection is established, the web browser and the server can exchange data freely. Either party can initiate a data transfer at any time for as long as the connection is open. For example, the server might push a stock-price update to the web browser, or the web browser might send a user's move in a game of chess.
  6. Either the web browser or the server closes the WebSocket connection.

WebSocket vs HTTP: How Does WebSocket Compare to AJAX or Comet?

Traditionally, when a web browser loads a web page, it follows these basic steps (simplified here for expository purposes):

  1. Open a short-lived connection to a web server.
  2. Send one or more requests for a limited number of resources (e.g., .html, .gif, .jpg, .png, .css, and .js files).
  3. Receive resources from the server.
  4. Close the connection to the web server.

The preceding architecture was designed primarily for document retrieval, where web browsers load static web pages from web servers. However, web applications that require frequent, timely updates are not well served by HTTP's traditional document-centric design.

Consider a hypothetical mobile-web application—let's call it "Friend Finder." Friend Finder lets friends share their current location with each other. When someone's location changes, the Friend Finder client sends the new location to the Friend Finder server. The Friend Finder server then forwards the new location to all connected friends.

Now imagine implementing Friend Finder using traditional HTTP.

When a user's location changes, the Friend Finder client uses a standard HTTP request to send the new location to the server. No problem so far. Next, the server needs to send the new location to the user's friends. But in traditional HTTP, the server cannot initiate data transmissions to those friends. The server cannot send data to the client unless the client explicitly asks for it via an HTTP request. In Friend Finder, this means that the server cannot send User A's location to User B unless User B asks for it. And given that User B always wants to know User A's location, User B has only one choice: it must constantly ask the server for User A's latest location—even if User A has not even moved. And the same goes for all connected users. In the HTTP implementation of Friend Finder, every user must constantly ask the server for the latest location of every friend, whether or not anyone has moved.

In an HTTP implementation of Friend Finder, clients would request friend locations using either standard polling or long-polling (aka "Comet"). In the standard-polling implementation, clients ask for friend locations by opening a new JavaScript XMLHttpRequest at regular intervals (say, every five seconds). In the long-polling implementation, the server holds client requests open until it has data to send, thus reducing unnecessary requests and improving responsiveness.

But whether Friend Finder uses standard polling or long-polling, when friends aren't moving around much, most HTTP requests are completely unnecessary, and waste bandwidth and CPU time on both the client and the server.

Now imagine implementing Friend Finder using WebSocket.

The Friend Finder client starts a new session by establishing a persistent WebSocket connection. When the user's location changes, the client sends the raw data for the new location to the server, without headers or other overhead. Next, the server, which has a persistent connection to all active users, simply sends the new location to the user's friends. Because the connection is bidirectional, the server can push data to clients at any time, without waiting for client requests. If no one moves for an hour, no location messages are sent.

Compared with WebSocket, the traditional HTTP implementation suffers from two problems:

HTTP Problem 1: Unnecessary bandwidth consumption
Every single time the application sends or receives an HTTP request, lengthy HTTP headers are transmitted. For example, here are the request/response headers for a single typical HTTP request; they total 544 bytes:

POST / HTTP/1.1
Host: user1.net:10100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0.1) Gecko/20100101 Firefox/5.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Content-Type: text/plain;charset=UTF-8
Content-Length: 64
Origin: null
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Length: 517
Content-Type: text/plain

If Friend Finder were to poll for locations once a second, a single user would consume 44.8 megabytes of HTTP-header bandwidth per day (one 24 hour period).

If the Friend Finder service consistently had 1000 users connected, it would consume 43.77 gigabytes of HTTP-header bandwidth per day.

If the Friend Finder service consistently had 10,000 users connected, it would consume 42.75 terabytes of HTTP-header bandwidth per day.

WebSocket, by comparison, transmits only a tiny two-byte frame for each message it sends. Once the WebSocket connection is established, not a single byte of HTTP-header bandwidth is consumed.

HTTP Problem 2: Server cannot push data to the client
The traditional design of HTTP forces client applications to poll the server for updates. In a real-time application, polling has the following shortcomings:

  • Every poll spends CPU time opening and closing a TCP/IP socket, and constructing sending, and receiving an HTTP request
  • Polls are often redundantly sent when no new information is available
  • Every poll costs bandwidth, including HTTP headers
  • Data is only as fresh as the most recent poll; longer delays between polls result in less-responsive applications and "stale" data
  • To retrieve a server update, the client asks the server for data, then the server responds to the client. WebSocket data, by contrast, travels from server to client only. The total round-trip network time for a poll, hence, can be as much as double the time required to update a client via WebSocket.

What are the Benefits of WebSocket?

Compared to HTTP, WebSocket offers the following benefits:

  • Two-byte per-message overhead (no HTTP header), which translates to lower bandwidth and faster network communications.
  • Both the client and the server can initiate a data transfer at any time, which means applications can be built without polling (no Comet, no AJAX). Real-time applications, hence, become more responsive. Data can be delivered to clients instantly, without waiting for client requests.

Does WebSocket Replace HTTP?

No, WebSocket does not replace HTTP. HTTP is still the best choice for document retrieval. HTTP can also be appropriate for high-traffic applications where updates are batched and sent only occasionally (say, every 30 seconds or minute). WebSocket provides a complement to HTTP's feature set, and should be used together with HTTP in real-time, networked applications where responsiveness is important.

What is a WebSocket Server? Is Union a WebSocket Server?

Strictly speaking, any server that can send and receive data using the WebSocket protocol is a WebSocket server. For example, a WebSocket server might be a custom game server for a JavaScript-based online role-playing game. Or a WebSocket server might be nothing more than a simple push server that publishes every message it receives to all subscribers of a given channel.

In that sense, Union too is a "WebSocket server" because it supports WebSocket as a transport mechanism. But on top of the simple WebSocket transport layer, Union provides an extensive development API that includes rooms, shared variables, a distributed object model, user accounts, data storage, messaging, filters, firewall traversal, connection management, spectation, banning, load testing tools, data snapshots, server-side extensibility, security controls, and a long list of network-application programming tools.

Furthermore, in addition to WebSocket, Union also communicates using two other protocols: Adobe® Flash®'s XMLSocket and traditional HTTP. All three transports (WebSocket, Flash XMLSocket, and HTTP) can be used at same time over the same port. For example, a Union-based live technical support application could include a customer connected to Union over WebSocket using Google Chrome, a technical support agent communicating with that customer over traditional HTTP in Microsoft Internet Explorer, and an administrator viewing support-call statistics in Flash Player over XMLSocket.

For more information on Union's application-development API and transport mechanisms, see Hello Union.

How Do I Use WebSocket with Union?

No special code is required to use WebSocket with Union. Simply connect to Union Server normally with Orbiter or OrbiterMicro, Union's JavaScript client frameworks. When Orbiter connects to Union, it automatically checks for WebSocket support in the web browser or host environment. If WebSocket is available, Orbiter uses it.

For example, here's the basic code required to connect to Union Server with Orbiter:

var orbiter = new net.user1.orbiter.Orbiter();
orbiter.connect("tryunion.com", 80);

When the preceding code runs in a web browser that supports WebSocket (e.g., Google Chrome), Orbiter connects using WebSocket. But when the exact same code runs in a browser that does not support WebSocket (e.g., Microsoft Internet Explorer 9), Orbiter connects using traditional HTTP.

Here's a log excerpt showing Orbiter's WebSocket-detection process:

8/8/11 16:30:31.985 UTC-4 INFO: [ORBITER] WebSocket not found in host environment. Trying HTTP.
8/8/11 16:30:31.986 UTC-4 INFO: [CONNECTION_MANAGER] New connection added. [HTTPDirectConnection, host: user1.net, port: 10100, send-delay: 300].
8/8/11 16:30:31.986 UTC-4 INFO: [ORBITER] Connecting to Union...

To detect WebSocket support, Orbiter internally uses the following code:

if (typeof WebSocket !== "undefined") {
  // Browser supports WebSocket
}

Applications can also be configured to use WebSocket only, with no HTTP support, as follows:

var orbiter = new net.user1.orbiter.Orbiter();
if (orbiter.system.hasWebSocket()) {
  orbiter.getConnectionManager().addConnection(
               new net.user1.orbiter.WebSocketConnection("tryunion.com", 80));
}

Alternatively, applications can disable WebSocket entirely using the following code:

var orbiter = new net.user1.orbiter.Orbiter();
var connection;
if (orbiter.getSystem().hasHTTPDirectConnection()) {
  connection = new net.user1.orbiter.HTTPDirectConnection("tryunion.com", 80);
} else {
  connection = new net.user1.orbiter.HTTPIFrameConnection("tryunion.com", 80);
}
orbiter.getConnectionManager().addConnection(connection);
orbiter.connect();

Finally, applications can use the following code to disable HTTP failover in browsers that support WebSocket:

var orbiter = new net.user1.orbiter.Orbiter();
// If the browser supports WebSocket, but WebSocket fails, then don't try HTTP
orbiter.disableHTTPFailover();
orbiter.connect("tryunion.com", 80);

What Versions of WebSocket does Union Support?

Union Server supports both the legacy WebSocket protocol "Hixie" draft 76 and the official Hybi protocol, draft 7 and higher.

Which Browsers Support WebSocket?

As of August 2011, WebSocket is supported by the following browsers:

  • Google Chrome 10+
  • Apple iOS (iPhone, iPad) 4.2+
  • Safari 5.0+
  • Firefox 6.0+ (Hybi Draft 7)

For the latest list of browsers that support WebSocket, see the When can I use... WebSocket compatibility table and Wikipedia's WebSocket Browser Support table.

Raw WebSocket Code Example

Union developers do not need to write WebSocket code directly. Instead, applications connect to Union Server using the Orbiter class's connect() method, which uses WebSocket internally when available.

However, for the curious, here is a basic raw WebSocket code example, similar to the code Union uses internally to conduct WebSocket communications. Union's actual WebSocket-communication code can be viewed in the WebSocketConnection class.

var socket = new WebSocket("ws://example.com:80");

socket.onopen = function (e) {
  console.log("Connection opened.");
  this.send("Hello server!");
};

socket.onmessage = function (e) {
  console.log("Data received: " + e.data);
};

socket.onclose = function (e) {
  console.log("Connection closed.");
};

socket.onerror = function (e) {
  console.log("Connection error.");
};