Quantcast
Channel: ASP.NET 4.5 Hosting News (SuperBlogAds Network) » cheap asp.net 4.5 hosting
Viewing all articles
Browse latest Browse all 29

ASP.NET 4.5 Hosting :: Programming WebSockets Utilizing .NET 4.5 With the Asynchronous HTTP Handler and System.Web.WebSockets

0
0

WebSockets is a good neat function. Numerous server-side implementations exist, this sort of as SignalR and Socket.IO. The .NET 4.5 now provides developers a managed implementation of the WebSockets protocol. Following a quick introduction on WebSockets, without likely to the nitty-gritty particulars of the protocol itself, this article will concentrate within the .NET implementation. I’ll offer an explanatory demo regarding how to implement and use WebSockets utilizing the native classes from Method.Web.WebSockets namespace and System.Net.WebSockets

ahp_freehostNET

What is WebSockets?
WebSockets is really a new normal way for net apps to have a persistent relationship in between consumer and server. It allows bidirectional (“full-duplex”) communication between an online browser as well as the web server.

Preparing Windows to support WebSockets
To be able to have Windows 8 (or Windows 2012 for instance) assistance for WebSocket, we initial need to add some features towards the Windows operation system. This may be carried out making use of the “Turn Windows features on or off” control panel product. The features we’d like are :

  • .NET Framework 4.5 Advanced Services → WCF Services → HTTP Activation

    1gesbe

  • and also: Internet Information Services → World Wide Web Services → Application Development Features → WebSocket Protocol

    2dfbsdeb

Creating a generic asynchronous HTTP Handler
Let’s start of with creating a new item of type ASP.NET Handler.

3dfbsade

You may also utilize the Generic Handler file template, which produces an .ASHX. For this sample I’ll go together with ASP.NET Handler, even though. I think it’s cleaner.

Visual Studio generates a class that implements the IHttpHandler interface. We’ll change that to derive from your abstract base course HttpTaskAsyncHandler. Also, as opposed to employing an interface, we’ll override the IsReusable house and ProcessRequest approach. Every thing is run asynchronously, so we seriously depend upon the async/await keywords and phrases as well as the task class. We’ll retailer the incoming WebSocket instance within a personal house, thus permitting us to get in touch with it’s techniques from inside of our class. The code must search such as this:

using System.Net.WebSockets;
using System.Threading.Tasks;
using System.Web;
 
namespace StockTickerDemo
{
    public abstract class WebSocketAsyncHandler : HttpTaskAsyncHandler
    {
        public override bool IsReusable
        {
            get
            {
                return false;
            }
        }
 
        private WebSocket Socket { get; set; }
 
        public override async Task ProcessRequestAsync(HttpContext httpContext)
        {
            await Task.Run(() =>
            {
                if (httpContext.IsWebSocketRequest)
                {
                }
            });
        }
    }
}

Notice that we’re producing a generic class implementation. Though this class will not outline summary methods, it’s going to only find it is usefulness whenever a specialised class derives from it. Therefore the WebSocketAsyncHandler class is marked summary. Also note that the code we apply is wrapped inside a Task occasion.

Defining the WebSocket concept handlers
When the HTTP ask for is in reality a WebSockets ask for, the WebSocket occasion is saved inside the corresponding home. Then we should also examine the State home of that occasion. Dependent on it’s price, we get in touch with the corresponding virtual approach. The following code illustrates this:

if (httpContext.IsWebSocketRequest)
{
    httpContext.AcceptWebSocketRequest(async delegate(AspNetWebSocketContext context)
    {
        this.Socket = context.WebSocket;
 
        while ( this.Socket != null || this.Socket.State != WebSocketState.Closed)
        {
            ArraySegment< byte> buffer = new ArraySegment< byte>( new byte[1024]);
            WebSocketReceiveResult receiveResult = await this.Socket.ReceiveAsync(buffer, CancellationToken.None);
 
            try
            {
                switch (receiveResult.MessageType)
                {
                    case WebSocketMessageType.Text:
                        string message = Encoding.UTF8.GetString(buffer.Array, 0, receiveResult.Count);
                        this.OnMessageReceived(message);
                        break;
                    case WebSocketMessageType.Binary:
                        this.OnMessageReceived(buffer.Array);
                        break;
                    case WebSocketMessageType.Close:
                        this.OnClosing( true, receiveResult.CloseStatusDescription);
                        break;
                }
 
                switch ( this.Socket.State)
                {
                    case WebSocketState.Connecting:
                        this.OnConnecting();
                        break;
                    case WebSocketState.Open:
                        this.OnOpen();
                        break;
                    case WebSocketState.CloseSent:
                        this.OnClosing( false, string.Empty);
                        break;
                    case WebSocketState.CloseReceived:
                        this.OnClosing( true, string.Empty);
                        break;
                    case WebSocketState.Closed:
                        this.OnClosed();
                        break;
                }
            }
            catch (Exception ex)
            {
                this.OnError(ex);
            }
        }
    });
}

 And of course the virtual methods:

protected virtual void OnConnecting()
{
}
 
protected virtual void OnOpen()
{
}
 
protected virtual void OnMessageReceived(string message)
{
}
 
protected virtual void OnMessageReceived(byte[] bytes)
{
}
 
protected virtual void OnClosing(bool isClientRequest, string message)
{
}
 
protected virtual void OnClosed()
{
}
 
protected virtual void OnError(Exception ex)
{
}

This is all the code we need to allows us to respond to messages from the client. Now we need to implement the code to send messages to the client. WebSockets allow us to send/receive binary or text messages (asynchronously!). This implementation is as such:

protected async Task SendMessageAsync(byte[] message)
{
    await this.SendMessageAsync(message, WebSocketMessageType.Binary);
}
 
protected async Task SendMessageAsync(string message)
{
    await this.SendMessageAsync( Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text);
}
 
private async Task SendMessageAsync(byte[] message, WebSocketMessageType messageType)
{
    await this.Socket.SendAsync(
        new ArraySegment(message),
        messageType,
        true,
        CancellationToken.None);
}

This generic class can be used in any ASP.NET project to implement your own custom WebSockets handler. All you need to do i s derive your class from it and implement the virtual methods.

Deriving a specialized class and implementing the specifics.
Now that we have written the generic class… we can implement the specifics, The code is pretty self explanatory actually:

namespace StockTickerDemo
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Threading.Tasks;
 
        public class StockTickerWebSocketAsyncHandler : WebSocketAsyncHandler
    {
        private static double[] FacebookQuotes
        {
            get
            {
                return new double[] { 28.38, 28.45, 27.53, 29.11, 29.23 };
            }
        }
 
        private static double[] GoogleQuotes
        {
            get
            {
                return new double[] { 758, 760, 764, 765, 769 };
            }
        }
 
        private double[] ActiveQuote { get; set; }
 
        protected override void OnMessageReceived( string message)
        {
            // Assignment prevents warning "Because this call is not awaited...Consider applying the 'await' operator
            // This is intentional => fire and forget
            Task task;
 
            if ( string.Equals(message, "STOP" ))
            {
                IndexTicker .DefaultInstance.Update -= this .IndexTicker_Update;
                this.ActiveQuote = null;
 
                task = this.SendMessageAsync( "Stopped" );
            }
            else
            {
                if ( this.ActiveQuote == null)
                {
                    IndexTicker .DefaultInstance.Update += this .IndexTicker_Update;
                }
 
                if ( string.Equals(message, "FB" ))
                {
                    this.ActiveQuote = FacebookQuotes;
                }
                else
                {
                    this.ActiveQuote = GoogleQuotes;
                }
 
                task = this.SendMessageAsync( "Started" );
            }
        }
 
        protected override void OnError( Exception ex)
        {
            // Assignment prevents warning "Because this call is not awaited...Consider applying the 'await' operator
            // This is intentional => fire and forget
            var task = this.SendMessageAsync( string.Format( "Something exceptional happened: {0}", ex.Message));
        }
 
        private void IndexTicker_Update( object sender, IndexTickerEventArgs e)
        {
            // Assignment prevents warning "Because this call is not awaited...Consider applying the 'await' operator
            // This is intentional => fire and forget
            var task = this .SendMessageAsync(this .ActiveQuote[e.QuoteIndex].ToString());
        }
    }
}

The IndexTicket is a single instance of a class that implements a basic Timer and fire’s an event every 5 seconds. Each time giving a random number between 0 and 4. This number corresponds to n index of the array with quote values. This timer is started and stopped in the Global.asax handlers for the web application. This simulates the stock quote ticker. All that the HTTP Handler does at start/stop is assign a event handler to the timer or remove it. When it handles the timer event it send a text message back to the browser client.

Registering the handler
Now that the handler code is ready, we should tell IIS to use this handler. This is done by registering the handler in the web.config:

<configuration>
  <system.webServer>
    <handlers>
      <add name="StockTickerWebSocketAsyncHandler" verb="*" path="StockTicker"
               type="StockTickerDemo.StockTickerWebSocketAsyncHandler, StockTickerDemo"
               resourceType="Unspecified" />
    </handlers>
  </system.webServer>
</configuration>

The web socket service is reachable through ws://<domain>/<site:ports>/StockTicker. The type attribute tells IIS where it can find the handler.
This concludes the server-side part of the demo.

The client HTML page.
Almost done. Now all we have to do is implement the client-side JavaScript and HTML. The HTML page is simple and straight forward. It has a script reference to jQuery and to the JavaScript files, which we will create further on in this article.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Stock Ticker using Web Sockets!</title>
    <script src="Scripts/jquery-1.9.1.js" type="text/javascript"></script>
    <script src="Scripts/StockTicker.js" type="text/javascript"></script>
</head>
<body>
 
    <div>
        <input id="stockQuoteFB" type="radio" name="stockQuote" checked="checked"/><label for="stockQuoteFB">Facebook</label>
        <input id="stockQuoteGOOG" type="radio" name="stockQuote" /><label for="stockQuoteGOOG">Google</label>
    </div>
    <div>
        <button id="startButton" value="Start">Start</button>&nbsp;
        <button id="stopButton" value="Stop" disabled="disabled">Stop</button>
    </div>
    <div id="stockQuoteInfo">
    </div>
 
</body>
</html>

Returned message texts will appear within the stockQuoteInfo div element.

JavaScript
In the JavaScript file we first create a client instance of a WebSocket class and hook up the event handlers so we can we process the messages send from the server :

var stockTickerService;
 
$(document).ready(function () {
    stockTickerService = new WebSocket( "ws://localhost:55555/StockTicker" );
 
    stockTickerService.onopen = function () {
        $( "#stockQuoteInfo").append("Connection opened
" );
    }
 
    stockTickerService.onmessage = function (message) {
        $( "#stockQuoteInfo").append(message.data + "
" );
    }
 
    stockTickerService.onclose = function () {
        $( "#stockQuoteInfo").append("Connection closed" + "
" );
    }
 
    stockTickerService.onerror = function (error) {
        $( "#stockQuoteInfo").append(error.data + "
" );
    }
});

 In the WebSocket constructor we pass the “ws:” url to the WebSocket service as it’s registered in the web.config. Also, we have a little custom JavaScript object to easily communicate the stock quote identifiers:

var NASDAQ = {
    'FACEBOOK' : 'FB',
    'GOOGLE': 'GOOG'
}

Now we only have to wire up the button click handlers to start and stop receiving messages. That is also done in the $(document).ready function:

$("#startButton").click( function () {
    if( $("#stockQuoteFB")[0].checked){
        stockTickerService.send(NASDAQ.FACEBOOK);
    } else {
        stockTickerService.send(NASDAQ.GOOGLE);
    }
 
    setUIState(true);
});
 
$("#stopButton").click( function () {
    stockTickerService.send( "STOP");
    setUIState(false);
});

 Now we can run our little web application. Pressing Start will initiate sending the stock numbers to the client:

4abdfbs

Pressing the Stop button will send a message to the server, which causes the HTTP Handler to unhook the event. As a result the web server will stop sending messages to the client.


Viewing all articles
Browse latest Browse all 29

Latest Images

Trending Articles





Latest Images