web browser compatible comet & websocket service
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:
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.
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)
Post Comment
yWswpH Im thankful for the blog article.Really looking forward to read more. Keep writing.
Dw3srH This great article has truly peaked my interest. I will take a note of your blog and keep checking for
OGlgkS A big thank you for your blog. Will read on...