Web Socket Tutorial

Web sockets are part of the new HTML5 suite of standards that is transforming the web into a full fledge development development platform capable of building rich internet applications only dreamed of before.

Web Socket Applications Explained

A web socket application has two components, a client side module that consumers a web socket service, and a server side service that provides the web socket end points. The client side API has been standardised as part of the W3C.org's standard setting process. As with all standard APIs they will eventually be supported in all major browsers. For current browser support see the web socket support page on caniuse.com.

Server Side Web Socket Support

The server side API depends on the technology platform you are using and usually requires support from the web server that hosts your service. Currently there are libraries available for different stacks to implement web socket functionality if there is no native support in your web server. For example Apache HTTP does not support web sockets at this time of writing. For example there is Ratchet for PHP while for Java Glassfish 4.0 already has support and Apache Tomcat 8.0 will support web sockets when it is released. The recently released Java EE 7 has client side and server side APIs for web sockets. Node.js also has support for web sockets in the ws package (npm install ws).

The main take-away from this is to understand that it is the client side api that has been standardised and the server side api will depend on your technology stack, although the various implementations will look alike.

Web Socket Client Side API

The client side API  is very simple and consists of 1 constructor, 3 life-cycle events and 2 client side initiated event. The constructor is responsible for creating and initiating the connection to the service end point. The full api interface spec can be found at the W3C.org site. It is about one page in legnth so have a look and see how easy web sockets are to use.

Web Socket Client Side API
Constructor
new WebSocket(url)
Life Cycle Events
onOpen
onMessage
onClose
Client Generated Events
send
close

A simple API for a power new feature for web browsers.

Warning - Web Socket Confusion

One issue to be careful of when reading up on web sockets as at 2013 is that there are many different implementation of web socket support on the server and client side that are not standards compliant. So don't get confused when reading dated articles on web sockets which use a different API or suggest downloading a client side library to provide browser support for web sockets for older browsers when they do not comply with the standard. An example of such an implementation is the popular socket.io package for node which provides a client and server side library.

As time progresses along with browser support for web sockets, there will be less confusing material out there.

Web Socket Code Examples 

A simple example of client side code that simply sends messages to a web service. There is no bidirectional communication on this example. It is intended to show the basic web socket API without too much surrounding code.

Simple Send Message Client/Server

Client code

<!DOCTYPE html>
<html>
<head>
	<title>HTML 5 Meetup Web Socket Demo</title>
</head>
<script>

	var wsURI = "ws://localhost:8888";
	var websocket; 

	function init(){
		setupWebSocket();
		var elm = document.getElementById("btn");
		elm.addEventListener('click',function (){
			var msg = document.querySelector("#msg");
			websocket.send(msg.value);
			msg.value="";
		});

	}

	function setupWebSocket(){
		websocket = new WebSocket(wsURI);
		websocket.onopen = function (event){
			console.log("opened connection");	
		};
		websocket.onclose = function(event) {
			console.log("closed connection");
		};
		websocket.onmessage = function (msg){
			console.log(msg.data);
		};
		websocket.onerror = function(error){
			console.log(error.data)
		};

	}

	window.onload=init;	
</script>
<body>
  <input name="msg" id="msg" placeholder="Type message to send"/> 
  <button id="btn" type="button">Send Message</button> 
  <br/>
</body>
</html>

Server Side Node.js (WS) Code

var WebSocketServer = require("ws").Server;
ws = new WebSocketServer({port:8888});

var sockets =  [];

ws.on('connection', function(socket){
	
	console.log("opening connection...");
	
	
	socket.on('message', function(message){
		console.log(message);
		});
	
	socket.on('close',function(evt){
		console.log("closing");
	}
)});

A Simple, and obligatory chat client and server

Client Side HTML/Javascript for web socket chat client

<!DOCTYPE html>
<html>
<head>
	<title>HTML 5 Meetup Web Socket Demo</title>
</head>
<script>

	var wsURI = "ws://localhost:8888";
	var websocket; 

	function init(){
		setupWebSocket();
		var elm = document.getElementById("btn");
		elm.addEventListener('click',function (){
			var msg = document.querySelector("#msg");
			var chat = document.querySelector("#chat");
			chat.value = chat.value+msg.value+"\r\n";
			websocket.send(msg.value);
			msg.value="";
		});

	}

	function setupWebSocket(){
		websocket = new WebSocket(wsURI);
		websocket.onopen = function (event){
			console.log("opened connection");	
		};
		websocket.onclose = function(event) {
			alert("connection has been closed!");
			console.log("closed connection");

		};
		websocket.onmessage = function (msg){
			var chat = document.querySelector("#chat");
			chat.value = chat.value+msg.data+"\r\n";
			console.log(msg.data);
		};
		websocket.onerror = function(error){
			alert(error);
		};

	}

	window.onload=init;	
</script>
<body>
  <input name="msg" id="msg" placeholder="Type message to send"/> 
  <button id="btn" type="button">Send Message</button> 
  <br/>
  <textarea id="chat" rows="25" columnns=180></textarea>
</body>
</html>

Server Side Node.js Code

var WebSocketServer = require("ws").Server;
ws = new WebSocketServer({port:8888});
console.log("started chat server");
var sockets =  [];

ws.on('connection', function(socket){
       
       var mysocket = socket;

	console.log("opening connection...");
	
	sockets.push(socket);
	
	socket.on('message', function(message){
		console.log(message);
		sockets.forEach(function(tmpSocket){ 
			if (tmpSocket!==mysocket){
				try{
					tmpSocket.send(message);
				} catch (e){
				  	console.log("socket error");
				  	console.log(e);
				  	console.log("removing socket from active socket list");
				  	console.log("size="+sockets.length);
	        		  	var index = sockets.indexOf(tmpsocket);
				  	sockets.splice(index);
				  	console.log("size="+sockets.length);
				}
			}
			
		});
	});
	
	socket.on('close',function(evt){
		console.log("closing socket connection ...");
	        var index = sockets.indexOf(mysocket);
	        sockets.splice(index);		
		console.log("removed socket from active socket list");
	}
)});

Web Socket Presentation

I have attached a presentation I gave at the HTML5 Developer Meetup in Johannesburg in September 2013 as well as the code snippets from above.

Happy hacking