Visit the High Level Logic (HLL) Website
— Home of XPL (eXtensible Process Language)
It's like XML, but you can store source code in it.
By Roger F. Gay
WebSockets are finally coming of age. Implemented in most major browsers and promised soon by Microsoft, developers are itching to use native bidirectional (full-duplex) communication within their browser applications. No more cranky bloated work-arounds to do what obviously needs to be done in order to use browsers as a real application GUI. Along with that, comes a host of new functionality with HTML 5 and the already popular tricks of CSS 3.
Yet, because WebSockets are still quite new to most developers, the technology and how it is used still seems a bit mysterious to many. This tutorial should help lift the fog around what WebSockets are and how to use them in browser applications. All the JavaScript code in this tutorial is free and without registration. You will even have access to a live HLL WebSocket server to try it out on your own. (Note: Server is temporarily down.) If you've not yet learned to use WebSockets in browser apps, it's likely a lot easier than you think.
So, briefly, what the heck is a WebSocket anyway? Let's review a tiny bit of compressed history just to put things in context. Don't worry, you won't be tested on this section. Hopefully, you'll just find it a bit interesting and informative.
You've heard of HTTP. Functionally, that's when you click on a button and then sit and wait for a response while your browser is locked up. Then came AJAX, which solved the lock-up problem without ever leaving the world of point and click; also known as “request-response.” Request-response is the pattern you find in the vast majority of existing web pages. You click on something to get a response. You don't get information from the server unless you click to update. What if the server wants to send you some information without waiting for you to ask?
The desire to let the server communicate more freely has been so strong that there have been work-arounds for what became known as “push” technology. Still relying on HTTP, it was a trick. "Long-polling" is one of the techniques used to "push" information to browsers. The browser page is set-up to send a request to the server via AJAX. Then it just waits for a response. AJAX doesn't lock up the browser. You can continue to play in the page while AJAX waits. But you don't really need to do anything. Examples include email message notifications and stock price trackers that do not require that you click in order to update.
But enough goofing around, a group of developers finally said. Old-fashioned push work-arounds are inefficient and often cranky. What we really need is full-duplex that's easy for every app developer to use. That means browsers can receive messages from the server at any time, even if the browser is sending messages at the same time. Besides that, we can do this in a way that is much more efficient than old-fashioned HTTP. That latter consideration is a sign of our age. People care a lot nowadays about the amount of data being shipped around, and the efficiency of communication processes, much of which is wasteful. We just don't need repeated HTTP connections to maintain a communication channel. We can also implement message passing more efficiently. That's what they did with WebSockets.
Messages go either way at any time. So, for example, if you want to build a multi-player game in a browser, you can get updates based on what other players are doing at any time. No cranky bloat-ware work-arounds to get it done and no need to install special software on your own computer. WebSockets are supported directly by browsers. You have a browser installed on a variety of different devices, not just your PC. If it's up-to-date with WebSocket support, you're ready to go. And your small devices will love you for the efficiency of WebSocket technology. Faster action, less energy use, less heat.
Besides this tutorial, you can also look at a running demonstration in a more complex web page
by following the link of my two year old blog article on the original HLL WebSocket demo. When you get to the demo, you can click “Download HTML source code” at the top if you wish, but the demo code you find there needs to be run under an http server. And you can look at my previous article running a simple game using the HLL WebSocket server to drive one of the game characters.
Christian verses Flying Spaghetti Monster - HTML 5 Games, WebSockets, and AI
The part of any of the demos that actually addresses WebSocket communication is very similar to the tutorial code. It's always that way. It doesn't matter where you get your JavaScript code or how it's built into development tools and frameworks. Browsers do the technical heavy lifting. Application developers use the browser's capabilities through a few simple-to-use methods.
OK, so let's get to the meat of the tutorial. I'm going to show you how to set-up the JavaScript in any browser application to make use of WebSockets. I'll give you all the code in this tutorial. I'll give you the direct explanation and you should see how really simple it is. The full code for this tutorial is
here. You can simply copy-paste it into a text editor and save it to your computer using a name with an .htm or .html extension (Windows: File Type "All Files" and explicitly type the whole file name, including extension) and then click on the file to run it. You should see some text spill out onto the page very quickly.
The tutorial program will automatically connect to the WebSocket server, send a message to it, receive a message from it, and then disconnect. So, basically, it goes through all the basic steps in WebSocket communication, posts messages to you on the html page as it goes along, and then stops. I'll also explain where to alter the code for your application.
Just for completeness, let me explain that the tutorial code is written in HTML 5; that is, any browser with HTML 5 capabilities sees it as such. Here's why.
<!DOCTYPE html>
<html>
That's it. Declaring doctype html simply, means to all modern browsers that the code within can be interpreted according to the most up-to-date standard.
Now let's go through the code. At the top of the tutorial application, you'll see a few variables defined and a simple initialization function.
var wsUri = "ws://isr.servequake.com/echo";
var output;
var websocket;
var connected=false;
function init() {
output = document.getElementById("output");
doConnect();
}
wsUri provides the IP address of the HLL WebSocket server used in this tutorial, with its application name “echo”. It will become apparent as we move through the tutorial that the variable “output” is used for printing text to your page, “websocket” is a variable that will be used for the WebSocket object, and “connected” just keeps track of whether we're connected (true) or not (false).
The function init() is automatically called when the page is loaded because of a line of code at the very bottom of the JavaScript section: “window.onload = init;” (When the page is loaded, call init().) init() sets the value of “output” to a <div> at the bottom of the html page. That's where the text will appear. It then calls function “doConnect()” whose name gives away at least part of its purpose. doConnect() is actually simpler than it might first appear. I will explain.
The doConnect() function is the most complicated part of the tutorial; and yet, when you get through it, you'll look back and wonder how it could be so simple. By the time you've finished the tutorial, you'll know why. Scan through it and then read the detailed explanation below.
function doConnect() {
if (connected) {
writeToScreen("<span style="color: red;">You're already connected!</span>");
} else if (typeof MozWebSocket != "undefined") {
websocket = new MozWebSocket(wsUri);
} else if (window.WebSocket) {
websocket = new WebSocket(wsUri);
} else {
writeToScreen('<strong style="color: red;">ERROR: This browser does not support WebSockets.</strong>');
return;
}
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
Within all the conditions, look for “websocket = new WebSocket(wsUri);”. This is how you tell all the most up-to-date browsers to make the connection. As you saw above, the argument “wsUri” is the address of the WebSocket server application. Let me go over the necessary distractions above.
if (connected): I simply want to know first if we're already connected. If we are, the tutorial app says so. No need to connect again.
typeof MozWebSocket: “MozWebSocket” has to do with the integrity of the Mozilla browser team. There are browser versions that support development versions of WebSockets. These don't conform to the final finished standard and as active members in guiding development of the standard they also did some of their own experiments. They didn't want to confuse anyone by calling any of those things WebSockets, so they called them MozWebSockets instead. By leaving this condition in, even some older versions of Firefox should still be able to run the tutorial; but not if they're too old.
if (window.WebSocket): What you're looking for in up-to-date browsers is whether they support standard WebSockets in a standard way and this test can be given simply as “if (window.WebSocket)” (or if ("WebSocket" in window)). If the three tests fail, then the browser doesn't support WebSockets. We could do something then beyond simply sending a strong message about the old browser. We could initiate a fall-back such as long-polling or, perhaps more wisely, provide information about getting an up-to-date browser.
The final four lines in doConnect() are telling your browser session what to do when certain events occur. These events are connection opened, connection closed, message received from server, and error occurs. Each corresponding standard event, onopen, onclose, onmessage, and onerror, is attached to the “websocket” object that was defined just above in “websocket = new WebSocket(wsUri);”. We then specify what “handler functions” are called when each of these events happen. (“Handlers” handle the events … doing whatever you program them to do.)
“websocket.onmessage = function(evt) { onMessage(evt) };” for example, says that says that when a message comes in from the server, call the onmessage event handler function named onMessage(evt). “evt” is an object containing the incoming message.
Once doConnect() is complete, we have a running WebSocket connection, ready to send and receive messages until you close the connection. The tutorial program is set up to automatically run through three more of the events; sending and receiving messages, and closing.
function onOpen(evt) {
connected = true;
writeToScreen("CONNECTED");
doSend("WebSocket rocks!");
}
onOpen(evt) is one of the event handler functions specified in doConnect(). Now that we have attached it to the websocket object, it will be automatically called by the browser when a connection is made. So, when your connection is made, the three things that I have programmed into the tutorial onOpen(evt) function will happen. (In your app, you can program it to do whatever you want it to do.) First, the variable “connected” will be set to true. Second, the word “CONNECTED” will be written so that you will know that you are connected. And third, it will send a text message, “WebSocket rocks!” to the WebSocket server, using the function doSend(). (As far as I know, Kaazing made the phrase “WebSocket rocks!” popular among WebSocket nerds like me. I also believe that Kaazing was the only organization with a final standard WebSocket server before HLL.)
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
doSend() is not a WebSocket event handler. It is a function that sends messages to the server at your command. Call this function (written as you wish) any time you want to send a message to the server. The tutorial function doSend() writes the message for you to see on your web page, and then calls the standard, browser supported websocket.send method with the message as the argument. That's it! That's how messages are sent from browser applications. … send(message);
At the server end of the tutorial application, the response will be a message sent back. I always feel a little funny at this point in the simplest demonstration of WebSockets. This is after all, a request-response pattern that could be done with AJAX. OK, so you can use WebSockets for things that have been done using AJAX. But of course, that's not all you can do. The server can send messages any time that it wants to. The WebSocket onmessage event handler function is always waiting to receive and perform in full-duplex. Nope, AJAX doesn't do that. AJAX is asynchronous HTTP. It needs a request in order to send a response.
function onMessage(evt) {
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
The tutorial's onMessage(evt) message event handler function simply writes the message from the server to the browser display, and then it calls the browser method websocket.close(). Note that “evt” is, in this context, an object containing the message from the server. The actual text message is accessed from “evt.data”. Again, just to be sure there's no confusion here. Unless you're writing a chat application, you're going to want something different to happen in response to message events. Put whatever application code you need inside the event handlers.
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
The browser will understand when the connection has been closed and will automatically call the onclose event handler, onClose(evt), which will simply write “DISCONNECTED” to your browser display.
Hopefully, you've seen all this happen very quickly without ever seeing what onError(evt) does.
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
If you do get an error, you will be told about it in your browser display, in red text.
Let's summarize and take in how simple this all is. You connect and tell the browser about your event handler functions. You also have a send function that uses the browsers websocket.send() method. When an event occurs, the related event handler functions are automatically called to do whatever you've programmed them to do. As far as browser-side WebSocket communications are concerned; you make the connection and then go about the simple business of sending and receiving messages, at any time, in no particular order, as much as you like. The rest of your coding is application specific.