EDITING BOARD
RO
EN
×
▼ BROWSE ISSUES ▼
Issue 13

HTML5: Web Sockets

Radu Olaru
Senior Software Developer
@Small Footprint
OTHERS

If we think of the most important influence any protocol had over computer communications, it has to be HTTP. This protocol made possible the web we use daily which itself spawned revolution after revolution in these last years. The first web pages were mostly static, few having modest multimedia content. But after a while, complex applications started to emerge prompting developers to hunt and discover the new possibilities as well as the limits of the Internet at that time.

TCP and HTTP

Communication protocols allow long debates and discussions. In short, there is a protocol that defines communication between systems called TCP, and a protocol built upon that defining the communication between a web client and a web server, called HTTP. HTTP implements TCP communication but adds web specific features: a client calls for a web page, the server gives a response after which the communication is considered closed. For new information from the server, the client has to make a new call.

HTTP implements the simple and efficient communication between an application and a server offered by TCP, guaranteeing the destination of its received messages - but also limits the server to a single response. This kind of communication is useful for applications, but is far from being enough. The server is not allowed to send messages to the clients by itself. Any message coming from the server must be asked for by the client. If the server receives another useful information later, for example some data updates which the client has just asked earlier, it cannot deliver them until the client makes a new request.

From acceptable solutions to plugins

Over the years, many attempts have been made to bypass this case. Meanwhile the web applications got more and more complex, defined new tendencies and finally became compulsory for the majority of companies. The AJAX revolution created the illusion of a permanent connection between the server and the clients. Other attempts were made to force the HTTP protocol to emulate a permanent connectivity - but to no avail. A somewhat drastic solution were plugins which simply opened a new TCP port and forwarded messages there. Flash and Silverlight are probably the best known examples. Permanent communication with minimum lag seemed to need unpractical solutions competing with the rewriting of the whole HTTP protocol.

The solution? As HTTP is not a standalone protocol but works over TCP, if the browser could interpret that protocol it could permanently connect to a server to communicate without interruption. HTML5 defines a specification allowing just that: the interpretation of a communication protocol similar to TCP in a browser.

Upgrade to WebSockets

The implementation is also smart: the browser request a web page using HTTP, but the page is then able to change the connection to WebSockets:

var connection = new WebSocket(
"ws://site.org/echo", ["soap", "xmpp"]);
connection.onopen = function () 
{ connection.send("Ping"); };
connection.onerror = function (error) 
{ console.log("Error: " + error); };
connection.onmessage = function (e)
{ console.log("Server: " + e.data); };

We can see above the page initializing the websocket communication and setting up handlers for the connection events. When the connection opens, a Ping message is sent to the server. In case of communication errors, they are logged in the browser console. If the server sends a message to a client, it will also be logged in the console. Of course, any other instruction may be executed at each point.

By running the above code, no TCP port will be opened. The existing HTTP connection will simply receive an upgrade request, switching to a different communication protocol. The protocol used will not be HTTP anymore, but WebSocket - running over TCP.

In order to send messages, the server must also implement the WebSocket specifications. There are many libraries for the main programming languages and platforms which implement WebSocket.

Also we can send binary messages:

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);

Or files: var file = document.querySelector( "input[type="file"]").files[0]; connection.send(file);

TCP and HTTP differences

WebSocket switches the HTTP connection in a new one, similar with TCP. The resulting protocol is not raw TCP, but an upgraded version of it. WebSockets implements full duplex communication with the remark that the messages are not byte streams, but text streams (of course, binary data may also be sent).

The HTTP message sent to initiate the new communication method is the following

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

To which the server responds with:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

The exchange is identical with the protocol upgrade from HTTP to HTTPS. The HTTP message allows the servers to receive both HTTP and WebSockets connections on the same port, but the WebSockets upgrade involves protocol-specific messages.

Once the connection is done, the client and the server may exchange information in full-duplex. The data contains minimal overhead, basically having a small header followed by the message itself. Sent WebSocket data is called a message and a single message may be split among many communication pages sent separately (just like TCP). This allows messages with unknown size to be sent - the message is paginated, the last page being marked with a special end flag.

Proxy traversal

The WebSocket implementations will try to detect if the browser uses a proxy when connecting to a destination. If a proxy is detected, the client will use HTTP CONNECT to create a persistent tunnel.

Although the WebSocket protocol is not aware of any proxy and firewall, it uses an HTTP compatible handshake allowing servers to grant access to HTTP and HTTPS ports (80 and 443). WebSockets defines the ws:// and wss:// prefixes, indicating the type of required connection: simple or encrypted. Both use the same upgrade mechanism described before.

Of course, the proxy will have the final decision to allow WebSocket traffic or not. The main thing is the protocol does not require new ports to be opened nor the composition of complex messages, outside of the regular HTTP standard. Also, the protocol does not require any supplementary configuration to the existing firewalls - if the HTTP port is open, the WebSockets communication will work alongside HTTP.

WebSockets cu Node.JS

We have seen how simple WebSocket communication is initiated from the client using JavaScript. Well the server part is simple as well. Internet Information services requires version 8 together with further Windows configurations to allow the new protocol to work, but for brevity we will demonstrate a WebSockets server using Node.JS - and again, JavaScript:

var WebSocketServer = require("websocket").server;
var http = require("http");
var clients = [];
var server = http.createServer(function(request, response) {
// aici se procesează cererile HTTP
// dacă implementăm un server pur WebSocket, nu 
// trebuie să scriem nimic aici
});
server.listen(1337, function() { });
// inițializăm serverul WebSocket
var wsServer = new WebSocketServer(
{ httpServer: server });
wsServer.on("request", function(request) {
var connection = request.accept(null, request.origin);
// mesajele primite de la client vor fi 
// procesate aici
connection.on("message", function(message) {
if (message.type === "utf8") {
connection.sendUTF("Hello"); 
// trimite înapoi un mesaj la client
clients.push(connection);
// rețin clientul
}
});
connection.on("close", function(connection) {
for (var i = 0; i < clients.length; i++) 
clients[i].sendUTF("someone left");
});
});

Basically the work model is similar to the Observer pattern: a list of subscribers is stored. When the server has a message to publish, the message is sent to each member of the list.

Requirements and restrictions

As we have seen, WebSockets is more than an HTML5 API. The client communication instructions are standardized in the HTML5 specification - but the protocol must also be implemented on the server. The server part is specified in RFC 6455.

So WebSockets communication requires a browser which supports the protocol but also a server which implements it. Currently all mainstream HTTP servers have been updated to support WebSockets: IIS 8, Apache, LightHTTPD and of course Node.JS which can build compatible web servers. Still, the main restriction comes from previous versions of IIS - IIS 8 is available only in Windows 8.

As of browsers, again, all mainstream browsers allow WebSocket communication - but for companies requiring Internet Explorer, the only compatible version is Internet Explorer 10, available again only in Windows 8.

Resources and references

www.html5rocks.com/en/tutorials/websockets/basics/

www.websocket.org

developer.mozilla.org/en/docs/WebSockets

tools.ietf.org/html/rfc6455

Sponsors

  • comply advantage
  • ntt data
  • 3PillarGlobal
  • Betfair
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • MetroSystems
  • BoatyardX
  • Colors in projects

VIDEO: ISSUE 96 LAUNCH EVENT

Radu Olaru wrote also