HTML 5 Web Sockets

HTML 5 introduced a new specification for Bi-Directional communication or Full Duplex connection between the server and the client

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 many other unnecessary stuff that is just overhead. With HTML 5 Web Sockets all that overhead is minimized.

Conventional Techniques of Achieving Real-Time Communication

Polling

Polling is a technique in which a client continuously sends a 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 a 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 end the request. It provides us some benefits if the updates are not that frequent but if the updates are very frequent, say every few milli-seconds 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 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 a HTML Page on HTML 5 standards and on the server-side I will create a 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 a 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 a 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 a 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

using System;

using System.Net.WebSockets;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

using System.Web;

using System.Web.WebSockets;

 

namespace HandlerProject

{

    //Handler Class which is main entry point.

    public class WebSocketHandler : HttpTaskAsyncHandler

    {

        public override bool IsReusable

        {

            get

            {

                return false;

            }

        }

 

        //Socket Object, Although i have created a Static Dictionary of Scoket objects just to show the sample working. What i do is create this Socket object for each user and

        //keeps it into the dictionary. You can obviously change the implementation in real time.

        private WebSocket Socket { get; set; }

 

        //Overriden menthod Process Request async/await featur has been used.

        public override async Task ProcessRequestAsync(HttpContext httpContext)

        {

            //task is executed

            await Task.Run(() =>

            {

                //Checks if it is a Web Socket Request

                if (httpContext.IsWebSocketRequest)

                {

                    httpContext.AcceptWebSocketRequest(async delegate(AspNetWebSocketContext aspNetWebSocketContext)

                    {

                        Socket = aspNetWebSocketContext.WebSocket;

 

                        //Checks if the connection is not already closed

                        while (Socket != null || Socket.State != WebSocketState.Closed)

                        {

                            //Recieves the message from client

                            ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);

                            WebSocketReceiveResult webSocketReceiveResult = await Socket.ReceiveAsync(buffer, CancellationToken.None);

 

                            //Here i have handled the case of text based communication, you can also put down your hode to handle byte arrays etc.

                            switch (webSocketReceiveResult.MessageType)

                            {

                                case WebSocketMessageType.Text:

                                    OnMessageReceived(Encoding.UTF8.GetString(buffer.Array, 0, webSocketReceiveResult.Count));

                                    break;

                            }

                        }

                    });

                }

            });

        }

 

        //Sends message to the client

        private async Task SendMessageAsync(string message, WebSocket socket)

        {

            await SendMessageAsync(Encoding.UTF8.GetBytes(message), socket);

        }

 

        //Sends the message to the client

        private async Task SendMessageAsync(byte[] message, WebSocket socket)

        {

            await socket.SendAsync(

                new ArraySegment<byte>(message),

                WebSocketMessageType.Text,

                true,

                CancellationToken.None);

        }

 

        //This message is fired and parent can forget about this, what this method do is gets the message and push it to the various clients which are connected

        protected void OnMessageReceived(string message)

        {

            Task task;

 

            if (message.IndexOf("JOINEDSAMPLECHAT") == 0)

            {

                WebSocketDictionary.Sockets[message.Replace("JOINEDSAMPLECHAT:", string.Empty)] = Socket;

                foreach (string key in WebSocketDictionary.Sockets.Keys)

                {

                    task = SendMessageAsync(string.Concat(message.Replace("JOINEDSAMPLECHAT:", string.Empty), " Joined Chat."), WebSocketDictionary.Sockets[key]);

                }

            }

            else

            {

                if (message.IndexOf("BROADCAST") == 0)

                {

                    foreach (string key in WebSocketDictionary.Sockets.Keys)

                    {

                        task = SendMessageAsync(message.Replace("BROADCAST:", string.Empty), WebSocketDictionary.Sockets[key]);

                    }

                }

            }

        }

    }

}

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 in this web site. The code is given below.

HTML Page
 

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Web Socket Sample</title>

    <script type="text/javascript">

    

    var webSocket;

    var username;

 

    //Check is made if the WebSocket are supported on the browser or not and if they are supported then connection is established. As this is the sample i have created the

    //connection here on page load but you can also create the connection on click of the join button.

   function WebSocketTest()

   {

        if ("WebSocket" in window)

        {

            webSocket = new WebSocket("ws://localhost:801/default.Socket");

            webSocket.onopen = function()

            {

                //Connection Opened, if you want to do something while opening connection do it here

            };

        }

        else

        {

            alert("WebSocket NOT supported by your Browser!");

        }

   }

 

   WebSocketTest();

  

   //When 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

   function JoinUser()

   {

        username = document.getElementById('txtUserName').value;

        var joinButton = document.getElementById('btnJoin');

        webSocket.send("JOINEDSAMPLECHAT:" + username);

        username.disabled = true;

        joinButton.disabled = true;

   }

  

   //When the user writes it any message it is broadcasted to every user.

   function SendMessage()

   {

        var message = document.getElementById('txtMessage').value;

        webSocket.send("BROADCAST:" + username + ": " + message);

   }

 

    //Fired when message is recieved from the server and displays it in the user window.

    webSocket.onmessage = function (evt)

    {

        var messages = document.getElementById('divMessages');

        var received_msg = evt.data;

        messages.innerHTML = messages.innerHTML + received_msg + '</br>';

    };

 

    //fired when the connection gets closed

    webSocket.onclose = function()

    {

        alert("Connection is closed");

    };

 

    //Fired when there comes some error in the web socket connection

    webSocket.onerror = funtion (error)

    {

        alert(error.data);

    };

 

    </script>

 

</head>

<body>

    Username:

    <input type="text" id="txtUserName" />&nbsp;<input type="button" id="btnJoin" value="Join" onclick="JoinUser();" /><br />

    Message:

    <input type="text" id="txtMessage" />&nbsp;<input type="button" id="btnBroadcaseMessage" value="Broadcast" onclick="SendMessage();" /><br />

    <div id="divMessages">

    </div>

</body>

</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
 

<configuration>

    <system.web>

      <compilation debug="false" targetFramework="4.5" />

      <httpRuntime targetFramework="4.5" />

    </system.web>

  <system.webServer>

    <handlers>

      <add name="WebSocketHandler" path="*.Socket" verb="*" type="HandlerProject.WebSocketHandler" preCondition="integratedMode"/>

    </handlers>

  </system.webServer>

</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.