Introduction

a few months ago, i wrote a web communication application for a company competition based on a html5 feature: websocket. no wonder, websocket will become to be a very popular and useful way on web based communication and it turns out that windows based client application can be more and more replaced by web based client application because of the websokcet's coming. However, there is the reality that not all web broswers support websocket so far. In order to be compatible to old way, our pure web based application with websocket support can not be released to the market because most of 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 broswer are not able to use the advanced feature. Therefore, recently 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 ging 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.

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

Using the code

Server Side

Basically, server side classes structure is like below:

serverConnection.PNG

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

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

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 detemine the message is going to be sent to one particular user or all users from WillObject.To:

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.

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 first time connect server.

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, final user is able to communicate with server side. If we look at communicator object from object oriented perspective (we didn't really create 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 respectively behavior in comet and websocket. The "communicator" object will determine which real object will be applied for with below code:

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

another configuration object keep comet connection string as well as websocket connection string

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

final user will call the objects like below:

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 not matter in your vs2010 or in your iis. 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 begin with "Comet" or "Websocket", click the right one to send a message from clicking the button (sorry for the very much simple demo)

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"