The WebSocket API is the next generation method of asynchronous communication from client to server. Communication takes place over single TCP socket using the ws
(unsecure) or wss
(secure) protocol and can be used by any client or server application. WebSocket is currently being standardized by the W3C. WebSocket is currently implemented in Firefox 4, Chrome 4, Opera 10.70, and Safari 5.
What's great about the WebSocket API that server and client can push messages to each other at any given time. WebSocket is not limited in its nature the way that AJAX (or XHR) is; AJAX technologies require a request to be made by the client, whereas WebSocket servers and clients can push each other messages. XHR is also limited by domain; the WebSocket API allows cross-domain messaging with no fuss.
AJAX technology was a clever usage of a feature not designed to be used the way it is today. WebSocket was created for the specific purpose of bi-direction message pushing.
Focusing on the client side API only (because each server side language will have its own API), the following snippet opens a connection, creates event listeners for connect, disconnect, and message events, sends a message back to the server, and closes the connection.
// Create a socket instance var socket = new WebSocket('ws://localhost:8080'); // Open the socket socket.onopen = function(event) { // Send an initial message socket.send('I am the client and I/'m listening!'); // Listen for messages socket.onmessage = function(event) { console.log('Client received a message',event); }; // Listen for socket closes socket.onclose = function(event) { console.log('Client notified socket has closed',event); }; // To close the socket.... //socket.close() };
Let's take a look at the individual pieces of the snippet above. The argument provided to WebSocket represents the URL to the address listening for socket connections. onopen
, onclose
, and onmessage
methods connect you to events on the socket instance. Each of these methods provides an event which gives insight as to the state of the socket.
The onmessage
event provides a data property which contains the body of the message. The message body must be a string, so serialization/deserialization strategies will be needed to pass more data.
The syntax is extremely simple which makes using WebSockets incredibly easy...unless the client doesn't support WebSocket. Internet Explorer does not currently support WebSocket. There are a few fallback transports that you can use if the client doesn't support WebSocket:
Wouldn't it be great if an API was available that would provide WebSocket event handling, fallback transports, and a server side solution, all within one API? Luckily Guillermo Rauch has created Socket.IO.
Socket.IO is a WebSocket API created by Guillermo Rauch, CTO of LearnBoost and lead scientist of LearnBoost Labs. Socket.IO will use feature detection to decide if the connection will be established with WebSocket, AJAX long polling, Flash, etc., making creating realtime apps that work everywhere a snap. Socket.IO also provides an API for NodeJS which looks very much like the client side API.
Socket.IO is available for download at GitHub. You can include the socket.io.js
file or you can pull Socket.IO from CDN:
<script src="http://cdn.socket.io/stable/socket.io.js"></script>
With Socket.IO available in the page, it's time to create a Socket:
// Create SocketIO instance, connect var socket = new io.Socket('localhost',{ port: 8080 }); socket.connect(); // Add a connect listener socket.on('connect',function() { console.log('Client has connected to the server!'); }); // Add a connect listener socket.on('message',function(data) { console.log('Received a message from the server!',data); }); // Add a disconnect listener socket.on('disconnect',function() { console.log('The client has disconnected!'); }); // Sends a message to the server via sockets function sendMessageToServer(message) { socket.send(message); }
Socket.IO simplifies the WebSocket API and unifies the APIs of its fallback transports. Transports include:
You may set any of the Socket.IO instance's options with a second argument to the constructor. Options include:
port
- the port to connect totransports
- an array containing the different transport types in order by preference []transportOptions
- an object with additional properties to pass to the transportSocket.IO also provides the usual connect, disconnect, and message events that the native WebSocket API provides. Socket also provides an on method which wraps each event type, much the way Node does.
The server side solution provided by Socket.IO allows unification of the client and server side APIs. With Node, you create a typical HTTP server but then pass the server instance to SocketIO. From there, you create connection, disconnect, and message listeners much the way you did on the client side.
A sample server side script would look very much like this:
// Require HTTP module (to start server) and Socket.IO var http = require('http'), io = require('socket.io'); // Start the server at port 8080 var server = http.createServer(function(req, res){ // Send HTML headers and message res.writeHead(200,{ 'Content-Type': 'text/html' }); res.end('<h1>Hello Socket Lover!</h1>'); }); server.listen(8080); // Create a Socket.IO instance, passing it our server var socket = io.listen(server); // Add a connect listener socket.on('connection', function(client){ // Success! Now listen to messages to be received client.on('message',function(event){ console.log('Received message from client!',event); }); client.on('disconnect',function(){ clearInterval(interval); console.log('Server has disconnected'); }); });
You can run the server portion (assuming you have NodeJS installed) from command line with:
node socket-server.js
Now your client and server can push messages back and forth! Within the NodeJS script, you can create a periodical message sender using some simple JavaScript:
// Create periodical which ends a message to the client every 5 seconds var interval = setInterval(function() { client.send('This is a message from the server! ' + new Date().getTime()); },5000);
The server side script will push a message to the client every five seconds!
Persevere creator Kris Zyp has created dojox.Socket
. dojox.Socket
wraps the WebSocket API in an API consistent with Dojo and provides a long-polling alternative if the client doesn't support WebSocket. Here's how you can use dojox.Socket
on the client side and Socket.IO on the server side:
var args, ws = typeof WebSocket != 'undefined'; var socket = dojox.socket(args = { url: ws ? '/socket.io/websocket' : '/socket.io/xhr-polling', headers:{ 'Content-Type':'application/x-www-urlencoded' }, transport: function(args, message){ args.content = message; // use URL-encoding to send the message instead of a raw body dojo.xhrPost(args); }; }); var sessionId; socket.on('message', function(){ if (!sessionId){ sessionId = message; args.url += '/' + sessionId; }else if(message.substr(0, 3) == '~h~'){ // a heartbeat } });
dojox.socket.Reconnect
has also been created to automatically reconnect if the socket loses connection. Look forward to dojox.Socket
debuting in Dojo 1.6.
There are many practical applications for WebSocket. WebSocket is ideal for most client-to-server asynchronous purposes, chat within the browser being the most prominent. WebSocket is used to day by most many companies because of its efficiency. Socket.IO is in use by many organizations and was very popular at the Node KnockOut contest.
There's not a great deal of information available about WebSocket so I've rounded up a few helpful resources:
Take a moment to download my demo and visit the resources provided above. The WebSocket API is the future of asynchronous messaging; Socket.IO is the best available resource for WebSocket in NodeJS and within the browser. Let me know your thoughts on WebSocket as I'm curious to know if you're as excited as I am by this new API!