Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Web Browser Compatible Comet & Websocket Service

4.78/5 (7 votes)
2 Jul 2011CPOL4 min read 80.2K   1.5K  
How to make subscription on webpage in terms of comet and websocket

Introduction

A few months ago, I wrote a web communication application for a company competition based on an HTML5 feature: websocket. No wonder, websocket will become a very popular and useful way for web based communication and it turns out that windows based client applications can be replaced more and more by web based client applications because of the websocket's arrival. However, there is the reality that not all web browsers support websocket so far. In order to be compatible to the old way, our pure web based application with websocket support cannot be released to the market because most people are using IE (it looks like IE9 supports websocket). Especially in China, IE6 users are everywhere. It makes me feel very bad that people with websocket support web browser are not able to use the advanced feature. Therefore, of late, I'm doing one job to combine comet and websocket together to implement web based communication.

Comet is one old but mature way to do web based communication with AysHttpRequest. I'm not going to introduce how to implement comet in this article. You can find lots of articles in CodeProject or you can simply have a look at my source code.

Please check:

What I'm doing is to open a comet communication service as well as websocket service on server with the same interface to client connection. Client will automatically select the proper service in terms of the client web browser. Then you can take care of your business data and send the data between web browser and server without considering what web browser you are using.

Using the Code

Server Side

Basically, the server side classes structure is like below:

serverConnection.PNG

WebsocketServer and CometServer manage their own connections respectively. WillWebCommunicator takes the responsibility to distribute messages between different services. For example, if there has one message sent from one user.

IWillCommunication will bring up messageArrived event no matter whether the message is from Websocket or comet. WillWebCommunicator will capture this event.

C#
public static void CreateWebSocketService(int port, string origin, 
	string location, int maxlinks = 100)
        {
            IWillCommunication communicator = new WebSocketServer(port, origin, location);
            communicator.Start(maxlinks);
            communicator.ClientMessageArrived += 
		new ClientMessageHandle(communicator_ClientMessageArrived);
            communicator.Connected += new ConnectionEventHandle(communicator_Connected);
            communicator.Disconnected += 
		new ConnectionEventHandle(communicator_Disconnected);
            _Connections.Add(communicator);
        }
        public static void CreateCometService(int maxlinks = 100)
        {
            if (_Connections.Contains(CometServer.Instance)) return;
            _Connections.Add(CometServer.Instance);
            CometServer.Instance.ClientMessageArrived += 
		new ClientMessageHandle(communicator_ClientMessageArrived);
            CometServer.Instance.Connected += 
		new ConnectionEventHandle(communicator_Connected);
            CometServer.Instance.Disconnected += 
		new ConnectionEventHandle(communicator_Disconnected);
        } 

and determine the message is going to be sent to one particular user or all users from WillObject.To:

C#
if (obj.To == "*")
{
    WillWebCommunicator.SendToAll(message.FromJson());
}
else
{
    WillWebCommunicator.SendToOne(obj.To, obj);
}

In WillWebCommunicator.SendToAll, message will be sent to all users both in Websocket server and comet server to make sure everyone get the message.

C#
public static void SendToAll(string message)
{
    foreach (IWillCommunication communicator in _Connections)     
	communicator.SendToAll(message);
}

In WillWebCommunicator.SendToOne, we will search both websocket server and comet server to locate the right user. There is a Token property to indicate one particular user with GUID, this token will be created when user connects to the server for the first time.

C#
public static void SendToOne(string token, string message)
{
   foreach (IWillCommunication communicator in _Connections) 
		communicator.SendToOne(token, message);
} 

Client Side

In order to make end users use remote service without considering the client webbrowser, I wrote a "communicator" singleton object to encrypt the connection to service. There 3 basic events in this object: ServerConnectedEvent, ServerDisconnectedEvent, MessageArrivedEvent. Through these 3 events, the final user is able to communicate with server side. If we look at communicator object from object oriented perspective (we didn't really create a class here, the object is created from asynomus function), we can simply assume there are actually 3 classes in the model: baseService, willCometConnection, websocketConnection.

clientConnection.PNG

I override open, close, send methods with respective behavior in comet and websocket. The "communicator" object will determine which real object will be applied with the below code:

C#
if ("WebSocket" in window) return willSocket();
else return willComet();

Another configuration object keeps the comet connection string as well as websocket connection string.

C#
var configuration = function () {
    return {
        websoketConnstring: "",
        cometConnstring: ""
    }
} ();

The final user will call the objects like below:

C#
configuration.cometConnstring = "CometConnection.ashx"; 
configuration.websoketConnstring = "ws://127.0.0.1:8181/WillSocket"
communicator.addMessageArrivedEvent(messageArrived);//messageArrived is your 
				//method to react MessageArrived event
communicator.open();

The simple thing you need to do next is to fill your messageArrived method, run your application and see the magic.

How to Use the Demo

Run up your willwebcommunication website in your VS2010 or (IIS needs some configuration, U suggest you run it in VS2010). If your computer is in the network, don't forget to change websocketConnstring to your IP address.

C++
configuration.websoketConnstring = 
	"ws://127.0.0.1:8181/WillSocket" //change your ipaddress 

Visit Default.html both in IE and Chrome to make sure you opened one comet connection and a websocket connection. In both webpages, you can find the other one's token beginning with "Comet" or "Websocket", click the right one to send a message by clicking the button. (Sorry for the very simple demo. I will improve it soon.)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)