HTML 5 Web Sockets

Introduction

 
HTML 5 introduced a new specification for Bi-Directional communication or Full Duplex connection between the server and the client. It is one of the most awaited technologies after AJAX that solves the various problems of connection management and communication between the server and the client.
 
Web Sockets are basically exposed by JavaScript in HTML 5; it can also work independent of the technologies on the client and the server, nearly all browsers support the HTML 5 Web Sockets feature as of now (all the latest versions) and the only restriction on the server-side is that the server should support a Web Sockets connection.
 
HTML 5 Web Sockets helps in achieving real-time communication using the stateless model of the Web, although earlier we would do this using some convention such as polling, long polling, and so on or using some other libraries like SignalR (that is now known as ASP.Net SignalR and is also recommended by Microsoft).
 
To do real-time communication (required in Gaming applications, chat engines and so on) between a client and a server (Using a stateless model), we would actually poll the server for the updated response every few seconds (Polling and Long Polling, I will explain both in a moment). The problem with this technique was that for every request that is sent to the server from the client, there is a Request and Response object created for that. In addition to this, authentication/authorization and many other things are relevant for each and every request. Also, the creating request and response object in itself is a very heavy process, and the entire page is sent back as a response to the client that includes headers and much other unnecessary stuff that is just overhead. With HTML 5 Web Sockets all that overhead is minimized.
 

Conventional Techniques for Achieving Real-Time Communication

 

Polling

 
Polling is a technique in which a client continuously sends an HTTP request to the server at a specified time interval and the response is sent from the server to update the information. So there is always some lag in the display of the updated information and additionally, the server treats every single request as a new request and thus it includes overhead. One of the major disadvantages is that even if the update is not available on the server, the client will continue polling to the server for the updated information. In this technique, there is no way you can configure the client to make a request to the server when an update is available because of the stateless model on which the web works.
 

Long Polling

 
Long Polling is a technique in which the client continues sending an HTTP request to the server and then the server waits for a specified interval to check for available updates to be sent to the client if there are then it creates the response and sends the updated response to the client, otherwise it sends the response to the client to send the request. It provides us some benefits if the updates are not that frequent but if the updates are very frequent, say every few milliseconds or every second then it is of no use over Polling.
 
To overcome this overhead, HTML 5 Web Sockets came to the rescue. Here I will explain how to work with HTML 5 Web Sockets with a sample application. Apart from all the conventional techniques of achieving Real-Time communication that works on HTTP Protocol, Web Socket Connections and Communication works on the Web Socket protocol.
 

Web Socket Attributes

 

Socket.readyState
 
This tells us the actual state of the Socket if the connection is opened, closed or not. The State is defined using integer values (0: Connection is not established until now, 1: Connection Established, 3: Connection is closed).
 
Web Socket Events
  1. Open: Fired when the connection is opened
  2. Message: Fired when message is received from the server
  3. Error: Fired when there is some error that has occurred in the socket connection
  4. Close: Fired when the connection is closed
Web Socket Methods
  1. Send: Used for sending data
  2. Close: Used for closing the connection
Here in this sample, I will create an HTML Page on HTML 5 standards and on the server-side I will create an HTTP Handler to which the client will make a Web Socket request and this handler will support the Web Sockets request or connections (for this, one thing is mandatory; the server should support or accept the Web Sockets request). The sample I am creating is a type of Chat Engine (I will let you know how to get it tested without making much effort, please remember that this is a sample application to show you how to use WebSockets and is not the best chat implementation in real applications, you can always create a better design than this for your applications).
 
It will be good I think to create an HTTP Handler first. All my .Net/C# code for HTTP Handler will be based upon .Net Framework 4.5 hosted on IIS 8. This is because IIS 8 provides the low-level support for Web Socket Connections and .Net 4.5 provides us some managed libraries (System.Web.WebSockets) for Web Socket objects.
 

Creating an HTTP Handler

 
Note: You can find detailed comments inline.
 
Open Microsoft Visual Studio 2012 then select "Add New Project (Class Library)". Here I have created a Class Library type of project named "HandlerProject". I have created a class in this project named "WebSocketHandler" that inherits from "HttpTaskAsyncHandler", in .Net 4.0 when we would create an HTTP Handler we would inherit it from an interface "IHttpHandler", but now .Net 4.5 provides a way to create an Async handler by just inheriting this base class where we need need to implement "BeginProcessRequest" and "EndProcessRequest" instead we just need to focus on "ProcessRequestAsync". I have also used a new feature of .Net 4.5, async/await. (If you don't know about this feature then please refer to this link: http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features since this is out of the scope of this article). In this Class Library, we need to import a reference for the DLL "System.Web".
 
Class Library Code
  1. using System;  
  2. using System.Net.WebSockets;  
  3. using System.Text;  
  4. using System.Threading;  
  5. using System.Threading.Tasks;  
  6. using System.Web;  
  7. using System.Web.WebSockets;  
  8.    
  9. namespace HandlerProject  
  10. {  
  11.     //Handler Class which is main entry point.  
  12.     public class WebSocketHandler : HttpTaskAsyncHandler  
  13.     {  
  14.         public override bool IsReusable  
  15.         {  
  16.             get  
  17.             {  
  18.                 return false;  
  19.             }  
  20.         }  
  21.    
  22.         //Socket Object, Although I have created a Static Dictionary of Socket objects just to show the sample working. What I do is create this Socket object for each user and  
  23.         //keeps it into the dictionary. You can obviously change the implementation in real-time.  
  24.         private WebSocket Socket { get; set; }  
  25.    
  26.         //Overriden menthod Process Request async/await featur has been used.  
  27.         public override async Task ProcessRequestAsync(HttpContext httpContext)  
  28.         {  
  29.             //task is executed  
  30.             await Task.Run(() =>  
  31.             {  
  32.                 //Checks if it is a Web Socket Request  
  33.                 if (httpContext.IsWebSocketRequest)  
  34.                 {  
  35.                     httpContext.AcceptWebSocketRequest(async delegate(AspNetWebSocketContext aspNetWebSocketContext)  
  36.                     {  
  37.                         Socket = aspNetWebSocketContext.WebSocket;  
  38.    
  39.                         //Checks if the connection is not already closed  
  40.                         while (Socket != null || Socket.State != WebSocketState.Closed)  
  41.                         {  
  42.                             //Recieves the message from client  
  43.                             ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);  
  44.                             WebSocketReceiveResult webSocketReceiveResult = await Socket.ReceiveAsync(buffer, CancellationToken.None);  
  45.    
  46.                             //Here I have handled the case of text-based communication, you can also put down your hode to handle byte arrays, etc.  
  47.                             switch (webSocketReceiveResult.MessageType)  
  48.                             {  
  49.                                 case WebSocketMessageType.Text:  
  50.                                     OnMessageReceived(Encoding.UTF8.GetString(buffer.Array, 0, webSocketReceiveResult.Count));  
  51.                                     break;  
  52.                             }  
  53.                         }  
  54.                     });  
  55.                 }  
  56.             });  
  57.         }  
  58.    
  59.         //Sends message to the client  
  60.         private async Task SendMessageAsync(string message, WebSocket socket)  
  61.         {  
  62.             await SendMessageAsync(Encoding.UTF8.GetBytes(message), socket);  
  63.         }  
  64.    
  65.         //Sends the message to the client  
  66.         private async Task SendMessageAsync(byte[] message, WebSocket socket)  
  67.         {  
  68.             await socket.SendAsync(  
  69.                 new ArraySegment<byte>(message),  
  70.                 WebSocketMessageType.Text,  
  71.                 true,  
  72.                 CancellationToken.None);  
  73.         }  
  74.    
  75.         //This message is fired and parent can forget about this, what this method does it gets the message and push it to the various clients which are connected  
  76.         protected void OnMessageReceived(string message)  
  77.         {  
  78.             Task task;  
  79.    
  80.             if (message.IndexOf("JOINEDSAMPLECHAT") == 0)  
  81.             {  
  82.                 WebSocketDictionary.Sockets[message.Replace("JOINEDSAMPLECHAT:", string.Empty)] = Socket;  
  83.                 foreach (string key in WebSocketDictionary.Sockets.Keys)  
  84.                 {  
  85.                     task = SendMessageAsync(string.Concat(message.Replace("JOINEDSAMPLECHAT:", string.Empty), " Joined Chat."), WebSocketDictionary.Sockets[key]);  
  86.                 }  
  87.             }  
  88.             else  
  89.             {  
  90.                 if (message.IndexOf("BROADCAST") == 0)  
  91.                 {  
  92.                     foreach (string key in WebSocketDictionary.Sockets.Keys)  
  93.                     {  
  94.                         task = SendMessageAsync(message.Replace("BROADCAST:", string.Empty), WebSocketDictionary.Sockets[key]);  
  95.                     }  
  96.                 }  
  97.             }  
  98.         }  
  99.     }  
  100. }  

Creating HTML Page in a WebSite

 
Note: You can find detailed comments inline.
 
Now add a new web site and host it on IIS 8. The port number on IIS that I used for my application is 801. Now add a new HTML Page on this web site. The code is given below.
 

HTML Page

  1. <!DOCTYPE html>  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4.     <title>Web Socket Sample</title>  
  5.     <script type="text/javascript">  
  6.       
  7.     var webSocket;  
  8.     var username;  
  9.    
  10.     //Check is made if the WebSocket is supported on the browser or not and if they are supported then the connection is established. As this is the sample I have created the  
  11.     //connection here on page load but you can also create the connection on click of the join button.  
  12.    function WebSocketTest()  
  13.    {  
  14.         if ("WebSocket" in window)  
  15.         {  
  16.             webSocket = new WebSocket("ws://localhost:801/default.Socket");  
  17.             webSocket.onopen = function()  
  18.             {  
  19.                 //Connection Opened, if you want to do something while opening connection do it here  
  20.             };  
  21.         }  
  22.         else  
  23.         {  
  24.             alert("WebSocket NOT supported by your Browser!");  
  25.         }  
  26.    }  
  27.    
  28.    WebSocketTest();  
  29.     
  30.    //When a user joins in by clicking in Join button, Message is sent to the server that the user joined in which is broadcasted for every user  
  31.    function JoinUser()  
  32.    {  
  33.         username = document.getElementById('txtUserName').value;  
  34.         var joinButton = document.getElementById('btnJoin');  
  35.         webSocket.send("JOINEDSAMPLECHAT:" + username);  
  36.         username.disabled = true;  
  37.         joinButton.disabled = true;  
  38.    }  
  39.     
  40.    //When the user writes it any message it is broadcasted to every user.  
  41.    function SendMessage()  
  42.    {  
  43.         var message = document.getElementById('txtMessage').value;  
  44.         webSocket.send("BROADCAST:" + username + ": " + message);  
  45.    }  
  46.    
  47.     //Fired when message is recieved from the server and displays it in the user window.  
  48.     webSocket.onmessage = function (evt)  
  49.     {  
  50.         var messages = document.getElementById('divMessages');  
  51.         var received_msg = evt.data;  
  52.         messages.innerHTML = messages.innerHTML + received_msg + '</br>';  
  53.     };  
  54.    
  55.     //fired when the connection gets closed  
  56.     webSocket.onclose = function()  
  57.     {  
  58.         alert("Connection is closed");  
  59.     };  
  60.    
  61.     //Fired when there comes some error in the web socket connection  
  62.     webSocket.onerror = funtion (error)  
  63.     {  
  64.         alert(error.data);  
  65.     };  
  66.    
  67.     </script>  
  68.    
  69. </head>  
  70. <body>  
  71.     Username:  
  72.     <input type="text" id="txtUserName" /> <input type="button" id="btnJoin" value="Join" onclick="JoinUser();" /><br />  
  73.     Message:  
  74.     <input type="text" id="txtMessage" /> <input type="button" id="btnBroadcaseMessage" value="Broadcast" onclick="SendMessage();" /><br />  
  75.     <div id="divMessages">  
  76.     </div>  
  77. </body>  
  78. </html> 
Now we need to configure the Handler for this WebSite, so just open the "Web.Config" file and paste the following code into it for configuring the Handler.
 
Web.Config
  1. <configuration>  
  2.     <system.web>  
  3.       <compilation debug="false" targetFramework="4.5" />  
  4.       <httpRuntime targetFramework="4.5" />  
  5.     </system.web>  
  6.   <system.webServer>  
  7.     <handlers>  
  8.       <add name="WebSocketHandler" path="*.Socket" verb="*" type="HandlerProject.WebSocketHandler" preCondition="integratedMode"/>  
  9.     </handlers>  
  10.   </system.webServer>  
  11. </configuration>  
And with this we are done, we are ready to use this chat application. Please find the following screenshots of it. What I have done here is I have opened two instances of Internet Explorer and Joined the chat with two separate users and you can see the communication going on.
 
Screenshot
 
HTML5-Web-Sockets.jpg
 
Also, I have attached a sample application code, that you can use. Just download it, host the website on IIS and configure the handler, the only thing after that that you need to do is, if you are hosting this sample application or website on some other port (other than 801) then just make changes in the HTML Page (change the port number where we are creating the Web socket Connection).
 
Hope it helps in understanding Web Sockets.


Similar Articles