Sunday, 19 April 2015

ASP.NET WebSockets basics

Back in 2012, ASP.NET 4.5 and IIS 8 shipped with built-in support for WebSockets. If you plan to support using WebSockets on the server today, you’ll most likely use SignalR, which makes this all quite easy, but I thought it would be educational to take a step back and see what’s involved in just using the framework’s basic support.

To try this out I created a new ASP.NET MVC web project.

I then added a new ‘Generic Handler’ item to the project and named it MyHandler.ashx

The contents of this hander are based on the example from What’s New in ASP.NET 4.5. It essentially echoes any content received back to the caller:


using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.WebSockets;

namespace DemoWebSockets
{
    public class MyHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.AcceptWebSocketRequest(ProcessWebSocket);
        }

        public bool IsReusable
        {
            get { return false; }
        }

        private async Task ProcessWebSocket(AspNetWebSocketContext context)
        {
            var socket = context.WebSocket;
            while (true)
            {
                var buffer = new ArraySegment(new byte[1024]);

                // Asynchronously wait for a message to arrive from a client
                var result = await socket.ReceiveAsync(buffer, CancellationToken.None);

                // If the socket is still open, echo the message back to the client
                if (socket.State == WebSocketState.Open)
                {
                    var userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
                    userMessage = string.Format("You sent: {0} at {1}", userMessage, DateTime.Now.ToLongTimeString());
                    buffer = new ArraySegment(Encoding.UTF8.GetBytes(userMessage));

                    // Asynchronously send a message to the client
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
                else
                {
                    break;
                }
            }
        }
    }
}

I then modified the index.cshtml page

<div class="row">    
<div class="col-md-12">
        <label for="msgText">Text to send:</label>
        <input id="msgText" type="text" /><br />
<input id="Trigger" type="button" onclick="CallWebSocket(); return false;" value="Send" />
        <hr />
        <div id="serverData">
</div>

<script type="text/javascript">
     var socket = new WebSocket("ws://localhost:51057/MyHandler.ashx");

     // Receive a string message from the server.
     socket.onmessage = function (msg) {
          document.getElementById("serverData").innerHTML = msg.data;
     };

     function CallWebSocket() {
         if (socket.OPEN) {
             // Send a string message from the browser.
             socket.send(document.getElementById("msgText").value);
         }
     } </script>

And here’s the finished product:

Screenshot showing example of web page

Youssef also shows how to create a handler using WebAPI, and server-side configuration to enable IIS WebSocket support.

No comments: