Here are the links to the previous installments:
- Introduction
- Threads vs. Events
- Using Non-Standard Modules
- Debugging with node-inspector
- CommonJS and Creating Custom Modules
- Node Version Management with n
- Implementing Events
- BDD Style Unit Tests with Jasmine-Node Sprinkled With Some Should
- “node_modules” Folders
- Pumping Data Between Streams
- Some Node.js Goodies
- The Towering Inferno
- Creating TCP Servers
HTML5 is definitely one of the hot topics du jour. There are several technologies that are part of the upcoming HTML5 standard, where one of the most exciting additions is WebSockets. This also means that it’s a quite popular topic in Node.js circles as well, as this technology tends to resonate well with the needs of real-time web applications. And I also admit that I’ve been putting off this topic way too long in this blog series. But hey, better late than never, right?
In short, WebSockets allow for bidirectional, cross-domain communication between the client (browser) and the server. When building web applications that need to frequently update the data that they’re displaying, one of the traditional approaches is to make use of long-polling and Ajax. Instead of letting the client drive the communication, we can now make use of WebSockets to invert this traditional model and instead let the server push the data to the client as soon as updates become available. Making use of WebSockets also reduces overhead compared to HTTP/Ajax because there are less headers involved that have to travel back and forth, which makes this kind of real-time communication more efficient. But, as always, there’s a major downside involved as well. Because the HTML5 standard is relatively new, only the most recent versions of the different browsers out there provide support for WebSockets out-of-the-box. Because WebSockets are not available in every browser, this means that we’re back to square one.
Enter Socket.IO.
Socket.IO provides a unified WebSocket API that works on every browser (yes, even IE 6) and it does that by supporting multiple communication transports under the hood. You can consider this library to be the jQuery of WebSockets ;-). The API provided by Socket.IO clearly resembles the native WebSocket API of HTML5. The WebSocket library consists of two parts, one for the client and one for the server. But enough of this blabbering. Let’s look at some code.
The simplest and most common example out there is that of a chat server. We need an HTTP server that returns a single HTML page where users can enter their name and start chatting. Sounds simple enough.
In order to serve a static HTML page and the client Socket.IO JavaScript file, we use a library called node-static. This is just a module that serves static files through HTTP, which also provides support for built-in caching.
This is how to set it up:
The static files that are meant to be sent to the browser are stored in a separate directory named ‘client’, which exists in the root folder of our project. We first create a file server instance, specifying the location of our static files, and simply serve the requested files when they are requested.
Next, let’s have a look at the content of the one and only HTML page that we’re providing for our simple chat application.
In order to establish communication with the server, we create a new socket and call the connect() method. Next, we register some event handlers and log some text to the screen in order to easily follow what is going on. We also use a little bit of jQuery to hook up to the click event of the send button. Here we use the socket that we created to send the message to the server. Notice how closely the API provided by Socket.IO resembles the native WebSocket API put forward by the current HTML5 specification.
And finally, here’s the code for integrating Socket.IO on the server.
var clientFiles = new static.Server('./client');
var httpServer = http.createServer(function(request, response) {
request.addListener('end', function () {
clientFiles.serve(request, response);
});
});
httpServer.listen(2000);
We first ask for the name of the user and for simplicity sake we assume that the first message received from a particular user is in fact the user name. From then on, every message that we receive from a user is broadcasted to all other connections.
Seeing this in action is pretty much what we expect.
I know that a real-time chat server application is the canonical example for demonstrating Socket.IO. But think of the real-world possibilities here. Suppose we have a web application where a user X changes some data and sends these changes to the server. These changes can then automatically be updated / merged when another user B is looking at the same data in order to reduce potential concurrency issues when this user B wants to change something as well. This greatly enhances the end-user experience. And there are a ton of other scenarios where this technology can make a difference.
The only aspect that somewhat troubles me about WebSockets is security. This is also the very reason why Mozilla disabled WebSockets in Firefox 4. But don’t dismiss it entirely either as more improvements will surely come soon.
I want to round off this post by pointing you to some other libraries that one can use to accomplish real-time communication between client and server. The first is node.ws.js, which is an minimal WebSocket library for Node.js. There’s also Faye, which is an easy to use publish-subscribe message system based on the Bayeux protocol.
Until next time and happy messaging!