Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET and Comet: Bringing Sockets Back

0.00/5 (No votes)
9 Apr 2008 1  
Implementing a socket based Comet solution in ASP.NET.

Sample Image

Introduction

Web pages and ASP.NET are wonderful tools, but as the old proverb goes, "if all you have is a hammer, everything seems like a nail". ASP.NET is a web technology, all of which exists to serve up resources to Web Browsers which request them. That's great, and it works for the vast majority of things currently on the Internet. In fact, when people think of the Internet, they mostly associate it with the ubiquitous World Wide Web model or its HTTP protocol. But, what if we want more...what if instead of Web Browsers just requesting resources, we want to push information actively out to them, without being asked first? Examples of this include: live wiki's, polls, chat, stock tickers, real-time auctions, and games.

This is where the existing paradigm fails, and we have to fall back to older technologies, the roots on which the Internet is founded....yes, I'm talking about actual two-way communication, interactivity, *gasp* sockets, TCP/IP!

Taking a step back, web requests can roughly be compared to a student asking a teacher questions. However, only the student is allowed to ask questions, the teacher cannot actively prompt the student with facts. This article sets out one experimental approach to breaking that model. Most of the current solutions, collectively called "Comet", involve the Web Browser keeping an active HTTP connection to the Web Server, like a student always keeping the teacher's attention. Presented here is another aproach, utilizing a "side-channel", where the "teacher" (that's the Web Server) doesn't spend as much attention or resources responding to pesky questions (web requests), and we can push information out instead, or engage in a more interactive way.

Background

This article is inspired and partially based on the work and code by Alex MacCaw, the developer who created the Juggernaut extension to Ruby on Rails. But, why leave all the fun to those dynamic language people? Can't we have that in ASP.NET too? The answer is "yes we can".

How do we communicate with the Web Browser without it making a request first? One solution is to have the Web Browser keep open a socket connection directly to the server using a small light-weight Flash component.

What are the benefits of this aproach?

  • It consumes much less Web Server resources. We are not dedicating any Web Server threads to responding to a "long-polling" request.
  • It's simple and easy to implement.
  • Good cross-platform support (any modern Web Browser that supports Flash 8, e.g., IE, FireFox, Safari, Opera).
  • Lower latency, no re-establishing connections, or other HTTP protocol overheads.

And yes, it does have drawbacks:

  • We need to install something on the Web Server or the network domain to accept these socket connections.
  • The embedded Flash component making the connection to the Comet server will not work behind firewalls or proxies that block non-HTTP ports.
  • It needs Flash and JavaScript enabled on the Web Browser.
  • It's a hack (though the same thing could be said about many, now ubiquitous, Web Browser technologies).

Using the Code

Comet applications can be divided into two categories:

  • "Server-push" applications where the Web Server pushes out information on updates and changes based on user events, e.g., live wiki's, polls, chat etc.
  • "Interactive" applications where an external process pushes information to the web browser in response to an event, e.g., stock tickers, real-time auctions, games etc.

Server-push

The work flow for using Comet in a server-push scenario is:

  1. The Web Browser requests a page from the Web Server, which includes the Flash Comet component, Comet JavaScript, and a unique authentication string.
  2. The Web Server registers the Comet connection with the "Comet Server", specifying its channel, its authentication string, and any initial state.
  3. The Web Browser opens a socket connection to the Comet Server, and sends its authentication string.
  4. The Web Browser sends data to the Web Server using postbacks.
  5. The Web Server responds to any postbacks or AJAX calls and publishes any updates to the Comet Server.
  6. The Web Browser responds to any updates from its Comet connection.

In code, with a simple "GuestBook" example:

  1. Placing a "CometControl" on the ASP.NET web page:
  2. <CometControl
        id="cometControl"
        runat="server"
        channel="GuestBook"></CometControl>
  3. Registering the Comet connection:
  4. protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            cometControl.Register();
    }
  5. Opening a socket is done automatically on the Web Browser if the "AutoConnect" property is set to true (the default).
  6. AJAX postbacks can be done with a simple UpdatePanel using ASP.NET AJAX extensions.
  7. The Web Server responds to AJAX events by publishing JavaScript code that is automatically evaluated on the Web Browser.
  8. protected void submitButton_Click(object sender, EventArgs e)
    {
        string name = nameTextBox.Text.Trim();
        string text = commentTextBox.Text.Trim();
        if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(text))
        {
            cometControl.Data = "guestbook_addComment ("
                + Wxv.Comet.Utility.SerializeJSON(
                    HttpContext.Current.Server.HtmlEncode(name))
                + "," + Wxv.Comet.Utility.SerializeJSON(
                    HttpContext.Current.Server.HtmlEncode(text)) + ");";
            cometControl.Publish();
        }
        commentTextBox.Text = "";
    }
  9. Finally, the Web Browser receives the data published on the Web Server and executes it:
  10. guestbook_addComment = function(name, comment)
    {
        var commentsDiv = document.getElementById ("comments");
        var e = document.createElement("blockquote");
        e.innerHTML = comment + " - " + name + "";
        commentsDiv.insertBefore (e, commentsDiv.firstChild);
    }

Interactive

The interactive scenario is very similar, but instead of the Web Browser doing postbacks or AJAX calls to the Web Server, the Web Browser uses its Comet connection to send data directly to an Application Client and vice versa.

The work flow for using Comet in an interactive scenario is:

  1. The Web Browser requests a page of the Web Server, which includes the Flash Comet component, Comet JavaScript, and a unique authentication string.
  2. The Web Server registers the Comet connection with the "Comet Server", specifying its channel, its authentication string, and any initial state.
  3. The Web Browser opens a socket connection to the Comet Server, and sends its authentication string, and the Comet Server tells any Application Clients whether a connection has been made on a channel they have subscribed to.
  4. The Application Client sends data to the Comet Server, which passes it onto any Web Browser which has connected on that channel.
  5. The Web Browser sends data to the Comet Server over its Comet connection, which passes it onto any Application Client which has subscribed to that channel.

The Web Browser code is still very similar, but now, instead of doing AJAX calls or postbacks, we can just send data to our actively listening Application Client over the Comet connection.

E.g.: in response to a button click in a "sound player" application:

function sounds_click(soundId)
{
    comet.send (soundId);
}

The Comet Server and Clients

The Comet Server is a simple event handling and messaging component that accepts two types of connections:

  • Comet connections from Web Browsers, these are always pre-registered and associated with a single channel.
  • Client connections from the Web Server, Comet Controls, or Client Applications.

It responds to the following Client events:

  • Register - A Client wants to allow a Web Browser to make a Comet connection.
  • Subscribe - A Client wants to listen to events on a specific channel.
  • Publish/Push - A Client wants to send data to an entire channel (Publish) or a specific Comet connection (Push).

It sends the following events to any Client that has subscribed to the related channel.

  • Connect - A Web Browser has successfully connected and authenticated with the Comet Server.
  • Disconnect - An authenticated Web Browser has disconnected from the Comet Server.
  • Send - A Web Browser has sent data to the Comet Server.

Both the Comet Server and the Client component, which Application Clients can be written with, are simple components. The Comet Server component is self-contained, the only interaction needed is to get it to start and stop, and it can be easily hosted in a Windows application, a Service, or even in the Web Server itself. Similarly, the Client is a simple component (which the CometControl already encapsulates) which exposes some simple methods and events (on a single thread) which can easily be extended to write your own Application Clients which can also be hosted in a variety of ways.

Summary

Web browsers opening socket connections to a server isn't actually that new. In their isolated little sandboxes, Java applets have been doing it since they were invented more then a decade ago, and Flash has had the capability for a while too. Microsoft's Silverlight will eventually be getting it in version 2.0. All that the Comet approaches are trying to do is get a similar capability directly within the web browser itself.

I've had fun with this project, exploring a Comet solution for ASP.NET. I don't pretend that it's anything more than it is, a toy project; so consume and eat it with a grain of salt (and credit me if it tastes nice). For this author however, it gave an interesting insight to what's possible.

History

  • 7-Apr-2008 - First version!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here