Building a Real time application with SignalR – Part 2

Brij Bhushan Mishra / Tuesday, March 15, 2016
 
 
This post is in continuation of my previous post where we discussed the needs, basics, configurations and transport mechanism of SignalR. In this post we will take this a step further by creating a sample application and analyze it further. Broadly, this post can be divided into two major parts: In the first part, we will be creating a sample and in the other, we will see how SignalR works in various environments and look into the communication request between client and server. To get a bit of background, check out Part 1 of this series here.
 
Working on the Sample
Server monitoring is one of the important tasks that we perform several times in various scenarios. One simple way to do this is via remote login to the server to monitor - or you can also use a client which connects the server, pulls out the required performance counters and displays that information accordingly.
In this example we are going to create a Server monitoring application which will show server resources utilization in real time. Our sample will be a basic one as our goal is to explain SignalR, and we will be reading some basic counters of the server and displaying that info on the UI. The UI will be updated every second, which is implemented via a timer on the server that pushes the data to the client every second.
We have already seen the required configuration in our previous post, so I’ve created an empty ASP.NET application and completed following steps:
        Installed SignalR Nuget package
        Added Startup class and added Configuration method
        Added an HTML file as Index.HTML and added jQuery, jQuery SignalR and Hub proxy.
The core part of any SignalR application is the HUB. There are two key things we will be doing here. First, reading the server resource counter, and second, pushing this information to the connected clients after a certain interval (in this example, 1 second). So let’s see the hub implementation:
        [HubMethodName("sendSeverDetails")]
 
        public void SendSeverDetails()
        {
            string processorTime;
 
            string memoryUsage;
 
            string diskReadperSec;
 
            string diskWriteperSec;
 
            string diskTransferperSec;
 
            // Getting the server counters
 
            GetServerUsageDetails(out processorTime, out memoryUsage, out
                diskReadperSec, out diskWriteperSec, out diskTransferperSec);
 
            // Broadcasting the counters to the connected clients
            Clients.All.SendSeverDetails(processorTime, memoryUsage,
                diskReadperSec, diskWriteperSec, diskTransferperSec, DateTime.Now.ToString());
        }
This is the core hub method. Here we are getting the server’s counters and then calling the client call back function and passing all the parameters. In this example, we are passing different parameters for each counter value, but we can also create an instance and pass a JSON string. As we need to keep updating the client with the latest counter, we need to call this method at certain intervals (here let’s say 1 second). This can be achieved via a timer as such:
       static Timer myTimer;
 
       private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(1000);
 
       public ServerDetailsHub()
        {
            myTimer = new System.Threading.Timer(UpdateUI, null, _updateInterval, _updateInterval);
           
            // Rest of the code removed for brevity. Download the solution for complete code
        }
// This is called via Timer after certain interval which inturn calls the core hub method
 
        private void UpdateUI(object state)
        {
            SendSeverDetails();
        }
Now let’s see our client side, where we have defined the call back method.
$(function () {
 
    var num = 1;
 
    // Declare a proxy to reference the hub.
 
    var hubProxy = $.connection.serverDetailsHub;
 
    // Create a function that the hub can call to broadcast messages.
 
    hubProxy.client.sendSeverDetails = function (processorTime, memoryUsage, diskReadperSec, diskWriteperSec, diskTransferperSec, when) {
 
        $('#tblServerUsage tr').last().after("<tr><td>" + num++ + "</td><td>" + processorTime + "</td><td>" + memoryUsage + "</td><td>"
            + diskReadperSec + "</td><td>" + diskWriteperSec + "</td><td>" + diskTransferperSec + "</td><td>" + when + "</td></tr>");
                 
    };
 
    // Start the connection.
 
    $.connection.hub.start();
 
});
Note – you can download the complete code for this example here .
In the above code, there are three things we are doing. First, creating the hub proxy; second, we defined the call back method which is called from the server and takes the same number of parameters; and third - which is another very important step - starting the hub. These steps do the negotiation with the server and create a persistent connection with server. In this demo, I am just adding a new row whenever the new data is received from the server.
Analyzing the application
SignalR creates a proxy JavaScript at run time which is used to create the proxy instance and establish the connection from the server. It can be seen if we navigate the proxy URL as follows:
In my previous post, we discussed that SignalR is capable of using multiple transport mechanisms and based on the scenario, it chooses one of the best options. So let’s see how the negotiation happens before selecting one.
The above traffic is captured while running the sample on IE 11. After downloading the required scripts, it downloads the hubs (which is the proxy we discussed above). Then you’ll see the red encircled area where it sends the negotiation request to the server. Based on that in the next request the webSockets transport gets selected. There are some other data with the request as well, like connection token, which is unique per client.
Let’s observe in the same application in a different environment:
These details were captured in Chrome, and here we see that apart from the common requests, it sends the negotiate request and chooses serverSentEevents as the transport and starts the request using the selected transport. Let’s see one more scenario:
Via IE9, we got three requests similar to those above, except the transport selected was foreverFrame, which starts the connection.
We see that based on the negotiation request, SignalR chooses one of the best options - and except for Web Socket, it requires one more request to start the connection.
Limiting the Transport Protocols
SignalR is very flexible and allows many configuration options based on need. We can configure to a specific transport or we can even provide the fallback in a specific order. This also helps in reducing the initial timeframe to start the connection as SignalR already knows which transport protocol to be used. We can provide any specific transport while starting the hub because it is the function which decides the selection of Protocol.
$.connection.hub.start({ transport: 'foreverFrame' });
We provide also the fallback options as
$.connection.hub.start({ transport: ['foreverFrame', 'longPolling'] });
Note – Similar to $.connection.hub.start(), the proxy also provides another function to stop the persistent connection as $.connection.hub.stop() and once it is called, we need to start the hub again to continue the communication between client and server.
Conclusion
In this post, we have created a server monitor sample, where the server pushes the server usage counter details at a certain interval to all the connected clients. We used a timer which after a certain interval raises an event, which first collects the counters and broadcasts to the connected client.
We also looked into the developer tools to examine various transport protocols used in various scenarios and saw that the same application uses different protocols based on the negotiations. We also saw how to narrow down the transport or even provide the specific protocol which reduces initial overhead.
I hope you enjoyed this post, and thanks for reading!
 
Create modern Web apps for any scenario with your favorite frameworks. Download Ignite UI today and experience the power of Infragistics jQuery controls.