Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

HTML5 Feature: (Canvas vs GDI+) & Duplex Communication (Websoket vs WCF) on Webpage

4.23/5 (8 votes)
11 Feb 2011CPOL4 min read 58.3K   1.5K  
HTML5 has some exciting features that allow us to build web based application like windows application

Background

A couple of months ago, my company had a competition on HTML 5. It reminded me pf an OPT subject when I was still a student. I brought this idea into the competition to maximized applying HTML 5 features in. There are two most important features I put in the competition:

  1. Canvas
  2. Websocket

There are three functions implemented in the application:

  1. P2P communication on webpage
  2. Animation on canvas
  3. Subscription on webpage

Introduction

  • I wrote a .NET windows forms application as websocket server. In the windows application, I implemented an OPT logic, and opened all key events to external programming through socket. Actually, any socket connections are able to get the data from the server.
  • I will not explain too much detail on OPT. Basically, the question is to produce P.

To produce P, two components need to be produced first: P1 and P2. We can make money from selling P as well as P1, P2. The price of P > the price of P1+P2.

There are 3 machines: one Red machine, one Green machine, one Yellow machine to produce P1, P2 and P.

To produce P1, the red machine needs to warm up for A minutes (I forgot the number) and to produce one P1 need ** dollars.

To produce P2, the green machine needs to warm up for B minutes, then work on P2 for C minutes. This is the first step. The second step is to warm up red machine for D minutes to work on P2 for E minutes. At this time, the red machine will stop producing P1 (we have only one red machine) and then green machine to continue working on P2 for the third step to work out P2.

To produce P, the yellow machine needs to warm up for F minutes. With one P1 and one P2, the yellow machine will produce one P for G minutes.

All the manufacturers need money.

Pay salary every week.

The question is: how to manage the production to get a maximum revenue.

I put an arithmetic calculation I think is the best in the window application. After you push the GO button, the application will run the arithmetic to get the maximum revenue.

Picture_3.png

I reproduced all effects on the windows form into a web page.

Picture_4.png

Using the Code

WebSocket

I referred to http://www.codeproject.com/KB/webservices/c_sharp_web_socket_server.aspx?bcsi_scan_84C04EB1A8996739=IUdio+8K+Vb+tVCNrQ5lbwYAAABJQgES&bcsi_scan_filename=c_sharp_web_socket_server.aspx to write websocket server The most important part for websocket connection is the handshake information. When chrome tries to connect one websocket server, it will send out a handshake information:

GET /chat HTTP/1.1 
Upgrade: WebSocket 
Connection: Upgrade 
Host: www.zendstudio.net:9108 
Origin: http://www.zendstudio.net 
Cookie: somenterCookie

When the server gets the information, reply:

HTTP/1.1 101 Web Socket Protocol Handshake 
Upgrade: WebSocket 
Connection: Upgrade 
WebSocket-Origin: localhost
WebSocket-Location: ws://localhost/chat

To set up the connection:

  • All the key data produced during P, P1 and P3 production will be subscribed through websocket. There are 3 structures defined to contain those information:
    C#
    //JSonObject has an extension method to convert the object to JSON object
    public class MileStoneMessage :JSonObject
        {
            #region Properties N:Total number; R: Remain number; S:Sales Number; 
            SR: Sales Revenue; M:Material
            public int P_N { get; set; }
            public int P_R { get; set; }
            public int P_S { get; set; }
            public decimal P_SR { get; set; }
            public int P2_N { get; set; }
            public int P2_R { get; set; }
            public int P2_S { get; set; }
            public int P2_U { get; set; }
            public decimal P2_SR { get; set; }
            public int P1_N { get; set; }
            public int P1_R { get; set; }
            public int P1_S { get; set; }
            public int P1_U { get; set; }
            public decimal P1_SR { get; set; }
            public decimal Salary { get; set; }
            public decimal MCost { get; set; }
            public decimal M_R { get; set; }
            public string T_P { get; set; }
            #endregion
        }
    public class ClientInstruction : JSonObject
        {
         
            public InstructionType Type { get; set; }
            public int Number { get; set; }
            public string Sender { get; set; }
            public string To { get; set; }
            public string Notice{ get; set; }
        }
  • Websocket server also accepts the below instructions to control the windows form which means, we can control windows form from web page.
    C#
    [DataContract]
        public enum InstructionType
        {
            [EnumMember]
            Auto=0,
            [EnumMember]
            Manual=1,
            [EnumMember]
            Start=2,
            [EnumMember]
            Pause=3,
            [EnumMember]
            Stop=4,
            [EnumMember]
            Timer=5,
            [EnumMember]
            InputP1=6,
            [EnumMember]
            InputP2=7,
            [EnumMember]
            Private = 8,//private message
            [EnumMember]
            Register = 9//new user
        }
  • Server sends out message:
    C#
    public void SendToAll(string message)
            {
                foreach (var c in Connections)
                {
                    try
                    {
                        if (!c.Send(message)) DisposedConnections.Add(c);
                    }
                    catch
                    {
                        DisposedConnections.Add(c);
                    }
                }
                foreach (var c in DisposedConnections)
                {
                    Connections.Remove(c);
                }
                DisposedConnections.Clear();
            }
  • JavaScript connect websocket server:
    JavaScript
    ws = new WebSocket('ws://' + document.getElementById("server").value + 
        ':8181/TWCompetition', 'ClientInstruction');
            ws.onopen = function () {
                status = 1;
                for (var i = 0; i < onOpenEventListeners.length; i++)
                    onOpenEventListeners[i]();
            }
            ws. önclose = function () {
                status = 0;
                for (var i = 0; i < onCloseEventListeners.length; i++)
                    onCloseEventListeners[i]();
            }
  • JavaScript receives messages from websocket:
    JavaScript
        ws.onmessage = function (evt) {
            var message = eval('(' + evt.data + ')');
            switch (message.Key) {
                case "InitData":
                    if (message.Trace.length > 0) RenderMoneyInitTrace(
                        "MoneyDashboard", message.Trace, "MoneyIcon");
                    break;
                case "Users":
                    OnlineUsers = message;
                    DisplayUsers();
    
                    break;
                case "Private":
                    var sender = message.Sender;
                    var conversationMessage = message.Message;
                    var name;
    
                    if(conversationMessage=="black you"){
                        if(blackyouObj!=null) {
                            blackyouObj.OpenBlack();
                            ClosePrivateWindow("PW"+sender);
                            return;
                        }
                    }
                    for (i = 0; i < OnlineUsers.Keys.length; i++) {
                        if (OnlineUsers.Keys[i] == sender) {
                            name = OnlineUsers.Names[i];
                        }
                    }
                    PrivateConversation(sender, name, conversationMessage)
                    break;
                case "Register":
                    Token = message.Token;
                    SendName(document.getElementById('name').value);
                    break;
                case "OneSecond":
                    for (var i = 0; i < onSecondEventListeners.length; i++)
                        onSecondEventListeners[i](message);
                    break;
                default:
                    for (var j = 0; j < onMilestoneEventListeners.length; j++)
                        onMilestoneEventListeners[j](message);
                    break;
            }
        }
    }
    
  • JavaScript sends back instructions:
    JavaScript
    var SendInstruction = function (type, number) {
        var json = JSON.stringify({ Type: type, Number: number });
        ws.Send(json);
    }

Canvas

To some degree, the syntax in JavaScript to draw shapes on canvas is kind of exactly like GDI+ syntax. JavaScript draws line:

JavaScript
ctx.beginPath();
ctx.moveTo(14, 10);
ctx.lineTo(23, 15);
ctx.lineTo(14, 20);
ctx.closePath();

JavaScript draws gradient:

JavaScript
grd = ctx.createLinearGradient(0, canvas.height-mywidth, 0, canvas.height);
grd.addColorStop(0, "gray");
grd.addColorStop(0.5, "white");
grd.addColorStop(1, "gray");

How to Demonstrate

  • Under WindowsOpt folder, double click opt.exe.
  • Have a look at the right upper corner of the Windows Form. Select a workable IP to build the client connection.

    ip.png

  • Click GO button on Game Control panel, the windows form begins to run the animation.

    gamecontr</p><p>•Under WebOPT folder, open WebOPT.html with the latest chrome</p><p>•Input the ip you got from the windows form into Server textbox on right upper corner and click Login (you can also input your personal name instead of keeping Will). If the connection is ok, you will see “websocket connection open” in the right Log panel. If there is “websocket connection close” means something I don’t know wrong.<img src=

  • After you set up the websocket, you will see the exact same animation like windows form on your webpage and you can also control the game.

    pa.png status.png

  • You can also see a thoughtworker is running on the screen

    tw.png

  • P2P communication, a little bit like Google talk
  • Login the WebOPT.html in a new tab with a different name. Then you will see online user list. Your name is in pink, others are in green.

    userlist.png

  • Click on someone in the list, a dialog will pop up on the left bottom corner.

    conversation.png

  • Write anything in and press enter. Then you are in a private conversation.

I designed a funny thing in, delete all text in the dialog and input “black you” in low case. The person you are talking to will have a black screen with a funny face on for a few seconds.

Every colorful thing you see in the webpage is written by JavaScript. There is no picture linked to the page. That is what I said - Canvas in HTML5 can replace GDI+.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)