WebSockets – the server

This is part two of my notes for my session about websockets that I’ll be presenting in two weeks at the Orlando Code Camp.

So… the server… having server that replies back whatever you send to it is fascinating but not very useful. I’ll extend the server from part one to allow the clients that are connected to it to talk to each other.

The first thing the server must do when receives a message is to parse it into a command and a payload:

public class Server : WebSocketHandler
{
    public override void OnOpen()
    {
       Say("hello from server");
    }

    public override void OnMessage(string message)
    {
        try
        {
            if (message == string.Empty)
                throw new Exception("empty command");

            string command;
            ParseCommand(ref message, out command);

            // handle known commands...

            throw new Exception("unrecognized command");
        }
        catch (Exception x)
        {
            Say("ERROR " + x.Message);
        }
    }

    public void Say(string message)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        base.Send(serializer.Serialize(message));
    }

    void ParseCommand(ref string message, out string command)
    {
        int pos = message.IndexOf(' ');
        command = message.Substring(0, pos);
        message = message.Remove(0, pos);
    }
}

The first thing a client must do after establishing connection is to introduce itself (“Hi, I’m John”) before he is able to send any commands. To do that the client will send a message “LOGIN John”. The first word of the message is the command (LOGIN) and the payload is the user name. When the server receives the message it will see the command LOGIN and will reply with “hello John”. No other commands will be allowed until the client has logged in.

if (command == "LOGIN")
{
    UserName = message;
    Say("hello " + UserName);
    return;
}

if (UserName == string.Empty)
    throw new Exception("unauthorized");

// other commands...

Now on the server we have a bunch of connections and we have the ability to assign a UserName to each connection. If we want want one connection to be able to send a message to another we need to build a little bit of plumbing in the form of a static class that keep a collection of all open connections:

public static class Connections
{
    static List<Server> connections = new List<Server>();

    public static void Add(Server server)
    {
        lock (connections)
        {
            connections.Add(server);
        }
    }

    public static void Remove(Server server)
    {
        lock (connections)
        {
            connections.Remove(server);
        }
    }

    public static Server Find(string userName)
    {
        lock (connections)
        {
            return connections
              .Where(s => s.UserName == userName)
              .FirstOrDefault();
        }
    }
}

We’ll have to change the HTTP handler to add the connection to that collection when a new connection is established:

public class WS : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
        {
            var server = new Server();
            Connections.Add(server);
            context.AcceptWebSocketRequest(server);
        }
    }
}

And also when a connection is closed it needs to be removed from the collection:

public class Server : WebSocketHandler
{
    public string UserName { get; private set; }

    // ...

    public override void OnClose()
    {
        Connections.Remove(this);
        base.OnClose();
    }
}

Now we are in business…

if (command.StartsWith("@"))
{
    string recipient = command.Remove(0, 1);

    var conn = Connections.Find(recipient);
    if (conn == null)
        throw new Exception("user " + recipient + " is not online");

    conn.Say(UserName + ": " + message);
    return;
}

To test that we can open 2 browser windows, in the first one will login as John and in the second one we’ll login as Mary. Then John can send Mary a message “@Mary How are you doing?”

WebSockets – introduction

This is the first of a series of posts about building real-time applications for Windows 8 (metro style) using websockets. These are my notes for a session that I will be presenting at the Orlando Code Camp on March 16th.

So what are websockets? Websockets are relatively new technology that allows two-way communication between a client and a server. In the past if we wanted to simulate a two way communication between the client and the server we had to do some form of polling where the client asks the server “do you have something for me?” and then the server have the opportunity to send back it’s message. The problem with that model is that most of the times there is no message to be send and so 90% of the whole communication is complete waste. With websockets the only communication that occurs is when either the client or the server have the message for the other. This is a lot more effective, scales better and is a lot easier to program.

Websockets are often viewed as a part of the HTML5 standard but in fact both server and client development is fully supported with the version 4.5 of the .net framework on a Windows 8 machine or Windows Server 2012 using IIS 8. Also all current version of the major web browsers support websockets including IE10, Firefox 6, Chrome 14 and Opera 12.

How does it work? The client send an HTTP GET request to the server asking to open a websocket connection. The server replies with a special “connection upgrade” response and after that both the client and the server can send messages to each other in any order. (This is obviously the simplified version, look in the F12 dev tools in Chrome to see the exact format of the request and the response).

Rome was not build in a day. Let’s create a simple client and a server to demonstrate the mechanics of the websockets handshake and communication.

– Using Visual Studio 2012 on a Windows 8 machine with IIS8 installed create a new Web Application. Configure the app to use IIS instead of the development web server.

– Install nuget package Microsoft.WebSockets

– Add a new HttpHandler called WS.ahx – this will perform the handshake

using Microsoft.Web.WebSockets;

public class WS : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
            context.AcceptWebSocketRequest(new Server());
    }
}

– Add a new class Server.cs that inherits from WebSocketHandler and overrides OnOpen(), OnMessage() and OnClose() methods

using Microsoft.Web.WebSockets;

public class Server : WebSocketHandler
{
    public override void OnOpen()
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        base.Send(serializer.Serialize("hello from server"));
    }

    public override void OnMessage(string message)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        base.Send(serializer.Serialize(message + " back"));
    }

    public override void OnClose()
    {
        base.OnClose();
    }
}

– And finally add a web page called default.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>WebSockets demo</title>
    <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.0.min.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.0.6-development-only.js"></script>
</head>
<body>
    <h1>WebSockets demo</h1>

    <input type="text" id="message" />
    <input type="button" id="send" value="Send" />

    <pre id="messages"></pre>

    <script type="text/javascript">

        $(function () {

            if (Modernizr.websockets) {
                log("### websockets supported");
            }

            if (!window.WebSocket && window.MozWebSocket)
                window.WebSocket = window.MozWebSocket;

            var host = "ws://localhost:8080/WS.ashx";
            var connection = new WebSocket(host);

            connection.onopen = function () {
                log("### connection open");
            };

            connection.onclose = function () {
                log("### connection closed");
            }

            connection.onmessage = function (message) {
                var data = window.JSON.parse(message.data);
                log("<<< " + data);
            };

            $("#send").click(function () {
                var message = $("#message").val();
                log(">>> " + message);
                connection.send(message);
                $("#message").val("");
            });
        });

        function log(s) {
            $("<div/>").html(s).appendTo($("#messages"));
        }

    </script>
</body>
</html>

– Set the default.html to be a start page and run the application. A simple webpage should appear with a textbox and a button. Whatever we say to the server the server should say it back. Now we are in business…

Last day at Xerox

new-xerox-logo

October 10th 2012 was my last day at Xerox. I started at ACS in April 2000 which was acquired by Xerox in 2009. On Monday I am going to a small company out of Tampa called AgileThought which won the award for a Best place to work in Tampa Bay couple of years in a row. I’ll miss ACS/Xerox but I’ve been ready for something new for a while…

Veni, vidi, vici

This weekend I attended a two-day Windows 8 event – a dev camp and hackaton in Seaworld Orlando. The event was organized by Microsoft and reminded me of the dev events from old days – very well-organized and executed. The best part was that I won one of the 3 grand prizes for the hackaton – a Samsung slate and $500 gift card.

I presented a simple To Do List application. There are 3 columns for to do items (list, today and tomorrow) and the user can rearrange his list with drag and drop. I also implemented a share contract and a live tile showing the top 3 items. I even incorporated a palm tree which was one of the requirements for extra credit.

The app actually turned out pretty well for a one day effort and seems quite usable. I plan to submit it to the marketplace with almost no changes so I can test how the process works (and see how many people would pay 99c to be more organized)…

Registered for Build 2012

I just registered for the event of the year – Build 2012. This will be my first major conference and I am very excited. The registration opened couple of minutes early and by the time it was supposed to open the first 500 early-bird tickets were gone (I was able to get one). The whole conference sold out in about one hour. For comparison it took two months last year till it sold out. It seems that Microsoft is getting the developers more excited than ever…

Application Excellence Review

Yesterday was my Application Excellence Review with and engineer from Microsoft. The meeting lasted solid 2 hours, not like someone suggested around 15 minutes.

The requirement for the review is to have your app at least 70% ready and it should clearly show the UI and the features of the final app. The developer must complete and submit a long survey about every possible aspect of a metro style app as well as the results of the windows application certification kit (WACK) that comes with the SDK. So besides having your app ready you need to spend at least two hours preparing for the meeting.

The meeting started well, we had a nice chat about win 8 and the marketplace while the engineer was downloading my app from the microsoft support site where I had previously uploaded it. It was really hard for me to upload my 5 files and I guess it was as hard for him to download them. (The site is at least 10 years old and did not work for me most of the time)

After that I demonstrated how the app works, which features are implemented already and which are coming in the release. We also discussed my monetization strategy.

I was up for a good start… and then he run the WACK… and it failed!!! The WACK has never failed for me before and I run it again while I was talking to him and it worked on my machine (WACK WOMM) again… It will be fun times when I finally submit the app for marketplace certification… Now I was nervous. He looked at the report from when I run the WACK in the morning and said that it is not a requirement for the WACK to succeed at this stage but once I submit for certification it should work.

That was the first 20 minutes. For the next hour and a half we went thru every single question of the survey and we discussed every single possible feature that a metro app could implement.

Overall the meeting was very positive and the guy gave me several very good suggestions. Few hours later I received my token and today I registered my (free for 2 years) developer account.

Nokia Lumia 800

Yesterday I received my brand new and free Nokia Lumia 800. Any color that you like as long as it’s black… Euro power adapter. Good but not great packaging (my palm pre had better packaging then any other phone I’ve seen 2-3 years ago). Went to the local AT&T store and got my SIM card cut. The girl was very friendly and she was excited to see the phone that is not for sale yet… The whole trip took not more than 15 minutes and I was in the game…

First impressions: compared to my old samsung focus the nokia is thicker and heavier, the screen seems slightly smaller and is less bright. All the buttons are on the right-hand side as opposite to the samsung that has buttons on both sides. The phone came with a plastic cover which is a nice touch. It’s faster than the samsung as has a nice solid feeling.

Somehow I expected that after I login with my live ID all my apps and data will be there from the cloud. That is not the case. You login and then nothing. After setting up my google and work accounts contacts and calendars were synced. Then connected to Zune, installed some updates and had to setup syncing for my music, podcasts and pictures. After about an hour things were looking a bit better. Then I had to reinstall all my apps. Maybe not all but those 15 or 20 that I use often. Overall not a great experience. I hear another company does that better and sells a lot more phones…

Microsoft store will be selling that phone for $900 on Feb 14th. I don’t know what are they thinking. It’s nice but not $900 nice. Can’t wait to see the Lumia 900…

Day 1 of Running

Today is my first day of a 13 week running program. The goal is to run a 10k race on Fool’s Day (4/1). I need to prove myself. It is a nice and sunny day in Central Florida. 42F at noon. Cold. I wore my new running shoes, shorts, technical t-shirt and a hat. The hat was a good idea. Long sleeves would have been nice. Did not bring water. Did not need it. The program for today was to run for 1 minute, walk for 2 minutes, repeat 12 times. The first interval was alright, the second one was harder, the third one was even harder than the second. After 6 intervals/18 minutes I turned back. The second half was easier than the first half. Total distance – 2.4 miles, pace 15 min/mile. I ran a lot faster than the program prescribes but it was too cold to run slowly. The new shoes did make a difference, my shins almost did nor hurt. So, I made the first step, the rest should be a piece of cake (at least that’s what the book says)…