RSS

HTML5 WebSockets Revolution (?)

17 Feb

This post is mainly combined of two parts: a somewhat philosophical approach to WebSockets, and a technical example for pushing data from the server using WebSockets. If you’re just looking for the technicals, you can click here and skip the philosophy.

Every now and then comes a technology that revolutionizes how we program. You can argue what Revolution in software development means, but I just like to think of it as something that either really changed our everyday programming (e.g. Object Oriented, LINQ, Ajax) or something that is somewhat an architectural change (e.g. SOA, Cloud programming). Microsoft has issued plenty of technologies in the past decade, many of which could have been considered as revolutionary but have either failed in competition (e.g. Silverlight), or have improved the existing but weren’t really revolutionary in concept by themselves (e.g. WCF, WPF). Don’t get me wrong – I use Silverlight for all those things that cannot be achieved using plain HTML & JavaScript, but the tables have turned in favor of HTML5, also as far as MS is concerned. But, Silverlight for the browser will probably continue to fill-in the gaps where HTML5 is still lacking in functionality or lacking implementation. For example, IE9 doesn’t implement multiple input file upload yet, and even if it did, you can’t run a code that will compress the files prior to uploading them – this is solvable using Silverlight.

Looking for the “what’s new” in .NET 4.5 got me reading about “Support for WebSockets Protocol”. When I read it I was truly shocked and amazed, as I wasn’t aware of HTML5 WebSockets at all up to that point, and here before me lay the foundations to a possible revolution in web development architecture, no less. At first, one can read about WebSockets and think that it’s just another feature among many others, but I believe that it is revolutionary in concept. It revolutionizes the concept of request/response. Unlike regular client-server non-web applications which are free to “push” messages from servers to clients, the web architecture is built of the client initiating a request and the server responding with a response. The server is basically unable to “push” messages to the client (excluding plugins which may be doing so). WebSockets allow you to do exactly that. In the MS article referenced above, their sample uses WebSockets to respond to an initiating client request. However, WebSockets could be used to perform the opposite, and upon opening a socket from the client – have the server initiate from then on and push messages to the client without having the client to initiate a request as before.

So what’s so revolutionary? I can think of two main things: 1) No more polling and 2) content can be controlled and pushed from the server without having the client initiate a request.

Polling
This will surely be a winner here. Web applications today are more and more “live”. Our clients browse to our website and receive “live” updates about events or messages. Just open up a Firebug’s Net panel in Facebook, Gmail or your favorite “real-time” stock related website and see polling in action. There are a couple of good pics that describe polling and “long polling” here. As you can easily see, polling is a periodical event which is triggered occasionally by a client “just to check” if there are updates from the server. This architecture is problematic in several ways, some of which are listed below:

  1. Polling isn’t “real time”. I believe that this isn’t really an issue for the majority of websites. After all, you can wait several seconds till you’re notified about that email that has already arrived on the server. But you might want to be notified immediately about a change in the stock market. So, if you have to have “real time” updates, you have to poll very frequently, which leads us to the next issue.
  2. If you have gazillions of users, polling may have a serious performance impact on your servers and as a result on your clients. And the more frequent the polling is, the more frustrating your clients will be.
  3. Lengthy operations: if you poll just to “keep alive” or to receive a minor update, polling may work quite smoothly. But what if your polling triggers a somewhat lengthy operation on the server? For example,  if your polling request results retrieved using a lengthy DB query, or a call to a Web Service that just happens to be down or busy? Multiply that by the number of your clients, and expect possible client timeouts or thread-short servers.

WebSockets clearly solve most of these issues. If a server maintains a list of client WebSockets, the client no-longer have to perform polling, as the server may notify them of changes. The server may either notify changes to specific clients (e.g. notify a client email application that an email has arrived to the user); or it can notify all the users (or groups of users) about a certain update. If you have gazillions of users, this update can be performed smartly, split across groups of users or different servers according to a certain logic which fits the nature of your application.

Program Flow
This is where the revolution can really occur, or die…. I’ll use ASP.NET WebForms and MVC as an example to this. The difference between WebForms and MVC is not so much in technology, as in concept. The general idea behind MVC is that requests arrive at a certain Controller, which retrieves a Model and decides which View should be displayed to the user, whereas in WebForms the request usually starts and ends at a referenced Page and rarely redirects the client to a different page (you can also use Server.Transfer, but this has it’s own challenges). So, in MVC, a Controller is responsible for deciding what to do, right? OK, so, this may be used as a concept with WebSockets too. Imagine a client application that loads an html page with the basic required layout, that registers a WebSocket with a server. Then imagine a Controller-like class on the server which decides what the user should see next, and pushes that to the client browser. Similar to MVC, a Controller class decides what the user should read next, but unlike MVC, that Controller class pushes the content to the client, without having the client request for it. The server has the initiative. Now, you may argue if this is desired, but this really depends on your web application. The web today is mostly interactive – the user has to request information and then the server responds. But think of how T.V. works (that is, non-interactive T.V.) – content is constantly pushed from the server onto the client. This includes media, commercials, real-time tickers etc. While interactivity is important to our users, some users don’t even know about stuff that exists in our website in the first place, so they don’t even know to request that content. How many times have you learned of something you were sorry that you didn’t know about sooner? How many times did you open your favorite news website and was disappointed that there was nothing new and you started to actively look for something new to read? You had to request for that information and look for it, instead of having smart servers push that information to you.

Example: You program a web application that focuses on entertainment, news or social networking. These usually thrive on “live” events: “just let us notify you of something that just happened, so you won’t leave our website.” This doesn’t have to end with polling for the latest news and displaying it in a ticker; You can change the entire html layout of the page according to the content you wish to display. A sports website can notify the client that an anticipated game you have registered to see is starting (“Let’s take you live to the game”); an entertainment website can notify a client when a show starts, or when the Oscar is being given to the Best Movie; A social network can push messages, events, pics and more; Forums can update their threads live. Another example would be “live profile-specific” commercials. You can “push” commercials to your clients upon certain events and profiles. Yet another example I can think of is that your website may offer assistance to your users based on their exposure level to certain features or content that they were never (or hardly ever) exposed to. I don’t know if these given examples convince you of the possible revolution here, but I’m sure that more examples can be thought of. The point is, that the web has a chance to become more content and logic driven and less request-based, where required. Even if the examples above can all be resolved using polling, I’m referring more to the architectural change that can be made due to the technology.

IIS

OK – this is a really frustrating thing now. Turns out that MS is currently supporting WebSockets only in IIS 8. When I read about WebSockets in ASP.NET 4.5, I downloaded Visual Studio 11 Developer Preview and installed it, only to find out that IIS 7 does not support it, and is not going to in the future according to this. I guess that MS is strategically not releasing new technologies for older O/S platforms in order to force us to update to their latest O/S. The same goes for .NET 4.5; as you can understand from the System Requirements of the Developer Preview, .NET 4.5 has a minimum request of Windows 7 (that’s right, not even Windows Vista). I believe that this really cripples us ASP.NET developers from taking advantage of WebSockets soon. Many of the web applications still use Windows 2003 with IIS6. It will be a real shame that browsers will support WebSockets a lot sooner than we can actually employ them, unless an open source alternative plugin will come up or MS comes to their senses.

So, I had to download and install Windows 8 Developer Preview, and install it on a VirtualBox (read here if you have to have custom resolutions to fit your screen). After that, I had to install VS11 Developer Preview because the VS11 that comes with the Windows 8 Developer Preview with development tools is a VS Express version that doesn’t support ASP.NET – and I wanted to debug stuff and not only run it. Finally, I had to install IIS with the WebSockets support:

After that, I was able to test WebSockets.

“Push, push!”

The first thing that I did was to try out MS’ WebSockets sample. This was working as expected, and sending content from the client using a WebSocket resulted in the server sending back that content.

Based on the MS sample, I proceeded with testing the theory described earlier, and maintain a list of WebSockets in order to push data from the server willingly (demonstrated by a simple timer which every 10 seconds transmitted the time-stamp from the server). Yes! it worked. And there was much rejoicing.

Here’s the screenshot (note, that neither Firebug nor IE10 Developer Tools fail to notify at this time that such interactivity took place):

Here’s the client code:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <script type="text/javascript">
        var socket;
        if (typeof(WebSocket) !== 'undefined') {
            socket = new WebSocket("ws://localhost/WebSockets/MyDispatcher.ashx");
        } else {
            socket = new MozWebSocket("ws://localhost/WebSockets/MyDispatcher.ashx");
        }

        // Receive a string message from the server.
        socket.onmessage = function (msg) {
            document.getElementById("serverData").innerHTML = msg.data;
        };
</script>
    <form id="form1" runat="server">
    <div id='serverData'></div>
    </form>
</body>
</html>
  • Lines 9-13 instantiate a WebSocket. For FF, I had to add ‘Moz’ prefix as it is still considered experimental. IE10 uses WebSocket as the standard specifies it.
  • Lines 16-18 simply update the div on line 21 with whatever is being received from the server.

Here’s the server code. As it’s quite lengthy, I have embedded comments within (highlighted lines are explained below):

<%@ WebHandler Language="C#" Class="MyDispatcher" %>

using System;
using System.Text;
using System.Web;
using System.Threading.Tasks;
using System.Threading;
using System.Timers;
using System.Web.WebSockets;
using System.Net.WebSockets;
using System.Collections.Generic;

public class MyDispatcher : IHttpHandler
{
    // list of client WebSockets that are open
    private static HashSet<WebSocket> list = new HashSet<WebSocket>();

    // ensure thread-safety of the WebSocket clients
    private static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

    // timer to simulate server actions which initiate notifications to clients
    private static System.Timers.Timer timer = new System.Timers.Timer();

    // initiate timer
    static MyDispatcher()
    {
        timer.AutoReset = false;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Interval = 10000; // notify every 10 seconds
        timer.Start();
    }

    // when ellapsed, notify all clients what the date/time is
    private async static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        timer.Stop();

        locker.EnterReadLock();
        try
        {
            if (list.Count == 0)
                return;

            string userMessage = string.Format("server sent: {0}", DateTime.Now);
            var buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));

            foreach (var socket in list)
            {
                if (socket.CloseStatus == null && socket.State == WebSocketState.Open)
                {
                    // asynchronously send a message to the client
                    await socket.SendAsync(buffer, WebSocketMessageType.Text,
                        true, CancellationToken.None);
                }
            }
        }
        finally
        {
            locker.ExitReadLock();
            timer.Start();
        }
    }

    // entry point to the handler, when a client requests to open a WebSocket
    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
            HttpContext.Current.AcceptWebSocketRequest(MyWebSocket);
    }

    // web socket async handler
    private async Task MyWebSocket(AspNetWebSocketContext context)
    {
        WebSocket socket = context.WebSocket;

        // add socket to socket list
        locker.EnterWriteLock();
        try
        {
            list.Add(socket);
        }
        finally
        {
            locker.ExitWriteLock();
        }

        // maintain socket
        while (true)
        {
            ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

            // async wait for a change in the socket
            WebSocketReceiveResult result =
                await socket.ReceiveAsync(buffer, CancellationToken.None);

            if (socket.State == WebSocketState.Open)
            {
                // TODO: handle what the client sent and send a message back from here
            }
            else
            {
                // client is no longer available - delete from list
                locker.EnterWriteLock();
                try
                {
                    list.Remove(socket);
                }
                finally
                {
                    locker.ExitWriteLock();
                }

                break;
            }
        }
    }

    public bool IsReusable { get { return true; } }
}

I’d like to emphasize several things, despite the embedded comments:

  • Line 49: Although the list is supposed to be cleared of non-open WebSockets, it is a safety. This sample did not originally remove closed sockets, and I noticed that accessing sockets in the list just to check if their state was Open, sometimes results in a “cannot access Disposed object” exception. Currently there’s no catch clause in that location as I have not experience this ever since I got rid of them closed sockets, but you may want to consider doing so. BTW: that’s why I also query the nullable CloseStatus prior to querying the Open state: I’m hoping that it won’t result in that exception if there is a CloseStatus – but I added this later in development and I can’t tell for sure if it is really helping.
  • Line 80: That’s where the new opened WebSocket is stored in the list (or rather HashSet).
  • Lines 93-94: This is important: what these lines basically do, is to asynchronously wait for a message from the client. But, it seems like this method returns whenever the socket status changes. So, when await returns, either the WebSocket is open, and it means that the client sent something which can be handled, or the WebSocket is not open, which probably means that it is closing and should be removed from the list of sockets (Line 106).

So, that’s a possible template for having the server send data to the client without being requested to do so by a client request.

Summary:
To make a long story short, WebSockets seem like something that will definitely will be used in web applications in the future, even if just to replace polling. Whether this will lead to an actual architectural change – I haven’t the slightest idea. All I can say is that there are many examples of things that started as something “small” but evolved to a huge success. Who knows – maybe in the future the web will change from a world of a request/response to a more client-server approach?

One thing that does bother me is that IIS7 does not support this feature. For us ASP.NET developers this could really pose a limitation. It’s not that easy to upgrade existing O/S to the newest servers, especially if those servers are customers’ servers, and WebSockets aren’t a good enough reason to do so, at least not yet. I hope that someone at MS will realize that this is a mistake and will help change this decision from within.

Note:
It’s important to note that WebSockets are not a Microsoft-only feature and are an HTML5 concept. This means that it will work on all of the major browsers one day, and as you can see here, it is already supported on Chrome, FF and IE 10.

UPDATE: I urge you to go and read this post too, in which I came to a conclusion that unfortunately WebSockets may not be a full solution as it will be supported from IE10 only.

About these ads
 
4 Comments

Posted by on 17/02/2012 in Software Development

 

Tags: , , , , , , , ,

4 responses to “HTML5 WebSockets Revolution (?)

  1. Peter Moskovits

    20/02/2012 at 09:12

    Agree that WebSockets fundamentally change how we will build Web apps and how we’ll use the Web in the future.
    Here is one of the best WebSocket overviews I came along – highlighting the possibilities WebSockets can bring to our lives: http://blog.kaazing.com/2011/10/11/the-best-websocket-overview-out-there/.

     
  2. bfelda

    27/02/2012 at 20:38

    I found it disappointing that MS would require iis8 for websocket functionality. There are many other frameworks out there like Alchemy Websockets, Super Websockets, and the one I use alot is Fleck. These run just fine in IIS7, or hosted in an app. Much of the functionality is similar to that of Microsoft’s implementation so the switch over to .net in a 9 months probably won’t be too involved. As far as browsers go, I am using websockets on mobile devices as its built into Safari already for apple products, and Android I am using Opera, Firefox, or Chrome Beta. Really quite amazing technology. It gets the “WOW” factor when I demo stuff.

     
  3. Yaniv

    14/04/2012 at 23:36

    Great post, thanks!!!

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 66 other followers

%d bloggers like this: