Home Products Consulting Download Registration Support Events

Home
Up

Real-time Push data from HTTP server onto MS Silverlight clients

 

support@udaparts.com
UDAParts
05/18/2009

 

 

Contents

 

1.    Introduction

    Microsoft has been working hard to bring us a new cross-platform and cross-browser technology for developing rich Internet application having many features such as multimedia, animation, graphics and audio/video playback. Starting from version 2, MS Silverlight supports .NET development languages and its integrated development environments. This is a very good approach and a very good news to .NET developers. 

    To communicate with backend server, Silverlight uses a very limited version of Window Communication Framework (WCF), HTTP protocol (For example, the class WebRequest), and socket. In general, these approaches make a client/server request simpler, but these technologies do not have enough support to push data from a HTTP server onto Silverlight client because these technologies are either too complex to use (socket) or poor in performance and scalability (WCF PollingDuplexHttpBinding).

    Now, our SocketPro comes with a new adapter specifically written for making bi-directional communication between HTTP server and Silverlight super easy with better scalability. This short article is a simple tutorial to guide you use our SocketPro to push data from a simple SocketPro HTTP server to Silverlight clients.

2.    Communication architecture between Silverlight and SocketPro HTTP server

    SocketPro has a HTTP service as shown in this article. Further, as shown in this article, it also supports pushing data from HTTP server onto browsers by use of HTTP protocol through JavaScript. SocketPro HTTP server is written with 100% non-blocking socket communication. Its special design is superbly great for developing applications requiring the feature real-time notification among all types of clients such as web browsers, desktop applications, server applications, and pocket pc/smart phone applications. You can see the particular feature here.

    We further extend SocketPro to support bi-directional communication between Silverlight and SocketPro specific HTTP server through JavaScript (ujsonxml.js) by writing a small (16 kilo bytes) Silverlight library (SAdapterForSilverlight.dll). The communication architecture can be simplified as the following:

    Your .NET Silverlight code  <===> SAdapterForSilverlight.dll (C# code) <===> ujsonxml.js (JavaScript) <===> usktpror.dll (core native code) <===> SProAdapter.dll(.NET code)

    Note that the above left red part runs inside a browser and right blue part on server side. 

3.    Analyze sample code snippets

    There are two separate projects available for this tutorial.

  • MS Silverlight/browser client side: C:\Program Files\UDAParts\SocketPro\tutorial\CSharp(VBNet)\SilverPush.
  • SocketPro HTTP server side: C:\Program Files\UDAParts\SocketPro\tutorial\CSharp(VBNet)\Chat\Server. The server project is the same one as discussed at this article here.If you do everything correctly, you will get the following picture.

   

    Client side code:    At the very beginning, you need to refer SocketPro adapter for Silverlight (SAdapterForSilverlight.dll) from your Silverlight project, and its name space like 'using SocketProAdapter.ClientSide;'. On your html or asp.net page, you'd refer SocketPro adapter for JavaScript (ujsonxml.js) before silverlight.js like the below:

    <script type="text/javascript" src="ujsonxml.js"></script>

    At this time, once a page is loaded, you can set two callbacks like the below.

    public Page()

    {

        InitializeComponent();

        UHTTP.UChat.OnChatRequest += new DOnChatRequest(UChat_OnChatRequest);

        UHTTP.UChat.OnMessage += new DOnChatNotification(UChat_OnMessage);

    }

    The above code is simple. The first callback is used for tracking returning results of chat requests such as Enter, Exit, Speak and SendUserMessage. The second one is for tracking any messages from a remote SocketPro HTTP push server. Note that SocketPro adapter for Silverlight exposes one static object UHTTP, which internally has one static object UChat.

    The following code snippet shows you how to handle chat requests results.

    void UChat_OnChatRequest(CRequest Request, object Result)

    {

        switch (Request.Name)

        {

        case "enter":

            if (UHTTP.UChat.Chatting)

            {

                btnEnter.IsEnabled = false;

                btnSpeak.IsEnabled = true;

            }

            break;

        case "exit":

            btnEnter.IsEnabled = true;

            btnSpeak.IsEnabled = false;

            break;

        default:

            break;

        }

        txtMsg.Text = string.Format("Method = {0}, Result = {1}", Request.Name, Result.ToString());

    }

    As you can see, it is really simple! The following code snippet shows you how to send a message onto other Silverlight, desktop, server and device clients through chat request Speak. Similarly, you can make other chat requests at your will.

    private void btnSpeak_Click(object sender, RoutedEventArgs e)

    {

        int []groups = {1,2,8};

        UHTTP.UChat.Speak(txtMsgOut.Text, groups); //send a message onto groups (1 + 2 + 8) of clients

    }

    The code just speaks out how it is simple! To track all types of messages from other Silverlight, desktop, server and device clients, you can use the below code snippet.

    void UChat_OnMessage(CRequest Request, CHttpPush HttpPush)

    {

        switch(HttpPush.Type)

        {

            case MessageType.Normal:

            {

                string str = "";

                foreach (CChatMessage cm in HttpPush.Messages)

                {

                     string strGroups = "[";

                     if (cm.Groups != null)

                     {

                         for (int n = 0; n < cm.Groups.Length; n++)

                         {

                              if (n > 0) strGroups += ", ";

                              strGroups += cm.Groups[n].ToString();

                         }

                         strGroups += "]";

                    }

                    if (str.Length > 0)

                        str += "ß>";

                    if (cm.MethodName == "enter")

                        str += string.Format("Sender = {0}, Message = join groups = {1}", cm.Sender, strGroups);

                    else if (cm.MethodName == "exit")

                        str += string.Format("Sender = {0}, Message = {1}, groups = {2}", cm.Sender, "exit", strGroups);

                    else

                        str += string.Format("Sender = {0}, Message = {1}, groups = {2}", cm.Sender, cm.Message, strGroups);

                }

                txtMsg.Text = str;

            }

                break;

            case MessageType.ServerShuttingdownGracefully:

                txtMsg.Text = "SocketPro HTTP push server shut down gracefully";

                break;

            case MessageType.Timeout:

                txtMsg.Text = "Time out";

                break;

            default:

                txtMsg.Text = "Unknown message";

                break;

        }

    }

    Again, you can see how simple it is!

    The above covers all of message-related callbacks and requests, which is powerful enough to support your business requirements for real-time message among Silverlight clients, simple HTML pages, desktop applications, server applications, and device applications. For further readings, see this article here.

    Note that SocketPro fully supports HTTP protocol, which enables you send a HTTP request from a Silverligh onto SocketPro HTTP server. To do so, simply use an instance of CRequest inside SocketPro adapter for JavaScript as shown in the below. 

    private void btnDoMyRequest_Click(object sender, RoutedEventArgs e)

    {

        Dictionary<string, object> map = new Dictionary<string, object>();

        map.Add("Map0", 123.45);

        map.Add("Map1", null);

        map.Add("Map2", "A sample map string");

        object[] AComplexStructure = new object[7];

        AComplexStructure[0] = map;

        AComplexStructure[1] = "MyString";

        AComplexStructure[2] = DateTime.Now.AddDays(-2);

        AComplexStructure[4] = true;

        AComplexStructure[6] = 34567;

        object[] child = new object[2];

        child[0] = "myDate";

        child[1] = DateTime.Now.AddDays(-5);

        AComplexStructure[3] = child;

        CRequest reqComplex = UHTTP.CreateHttpRequest("MyCall", "/MyChannel");

        reqComplex.Add("Param0", m_lIndex);

        reqComplex.Add("Param1", 23.45);

        reqComplex.Add("MyParam", "A demo string");

        reqComplex.Add("ABoolean", true);

        reqComplex.Add("ADateTime", DateTime.Now);

        reqComplex.Add("AnArray", AComplexStructure);

        reqComplex.Add("CyeMap", map);

        m_lIndex = reqComplex.Invoke(delegate(CRequest myReq, string strResult)

        {

            HtmlPage.Window.Alert(strResult);

        });

    }

    We purposely show you how to send a complex request named as MyCall onto a remote HTTP server through channel (/MyChannel). Note the static object UHTTP exposes a static method CreateHttpRequest used for creating an empty HTTP request.

    Internally, SocketPro adapter for Silverlight constructs a JSON object through SocketPro adapter for JavaScript (ujsonxml.js) and send it onto server by default. You can use the above code to send any request easily.

    Note the class CRequest method Invoke supports synchronous computing for same-domain HTTP request, although we'll use asynchronous computing by default. However, technically it is not possible to do synchronous computing for cross-domain (site) HTTP request.

    The last important note is that SocketPro supports both same-domain and cross-domain (or site) chat request and message on the fly silently. If a message or request is same-domain, it will use AJAX. Otherwise, it uses JavaScript tag to complete it silently for you.

    Server side code:    It is superbly simple too! We have hidden all of HTTP chat and message from you. All you need to do is to use the class CHttpPushPeer. Because this sample server project is the same one as shown in this article, we like you to read this article here. As long as you read it, you are expected to know how to enable HTTP server push on server side.

    Here is the only code snippet which we like you to know. It shows you how to handle a HTTP request from a browser page or Silverlight client.

    protected override string OnProcessingRequest(string strMethod, string strVersion, string strId, Dictionary<string, object> mapParams)

    {

        switch (PathName)

        {

        case "/MyChannel":

            {

                CMyCall myCall = new CMyCall();

                myCall.method = strMethod;

                myCall.version = strVersion;

                myCall.callIndex = strId;

                myCall.parameters = mapParams;

 

                System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();

                string str = jss.Serialize(myCall);

                Console.WriteLine(str);

                return str;

            }

        default:

            break;

        }

        throw new Exception("Request not supported");

    }

    Here we simply serialize a request back into a JSON string and echo back request as returning result string. Note that you can also throw an exception. The exception message will be transferred onto its browser.

4.    Comparison to socket and WCF PollingDuplexHttpBinding  

    Our SocketPro approach has a lot of advantages over socket and WCF with PollingDuplexHttpBinding as well as other implementations. Here is the list.

  • Simpler without pitfalls at all: After having compared our approach with major samples published on Internet, We have found that SocketPro adapter for Silverlight is much much simpler and more elegant than socket and WCF with PollingDuplexHttpBinding. There are other samples available on Internet. You can compare our sample code with them. You'll have the same conclusion. Both socket and WCF with PollingDuplexHttpBinding have so many pitfalls and complexities so that you have to spend very much time to study it ahead.
  • Built-in integration with other pushes: It is considerably challenging to integrate Silverlight push with others like desktop applications, devices and middle tier servers. The integration of Silverlight with others is already out-of-box for you with SocketPro.
  • No firewall, proxy and NAT problems: Our SocketPro push uses HTTP protocol only. There are no firewall, proxy and NAT problems. This is an advantage over direct use of socket.
  • High performance and scalability: SocketPro is created with 100% non-blocking socket communication. As show in this article, it is much faster and more scalable than WCF. Further, SocketPro HTTP server is lighter than MS Internet Server. Its special design leads much better scalability and supports much more socket connections at the same time. It is estimated that our SocketPro HTTP server is able to support more than 5000 push connections from different Silverlight or web browser clients at the same time for a common server. If you have a very good server, it should support 10,000 push connections. If you use WCF PollingDuplexHttpBinding hosted in IIS, you can not get over 250 push connections.
  • Lower latency: Our SocketPro approach uses long-polling to reduce push time from server to browser. Usually the latency time is just the half of ping time from browser to server. Under the worst and very rarely cases, the latency time is the three times of ping time from browser to server. This level latency is comparable to direct socket communication. WCF with PollingDuplexHttpBinding can not have such a low latency.
  • Synchronous computing supported: As described in the above section, SocketPro supports not only asynchronous computing by default but also synchronous computing for same-domain HTTP request. In case you like to use synchronous computing to simplify coding logic, you can do so with SocketPro adapter for Silverlight. In comparison, WCF for Silverlight does not support any synchronous computing at all.
  • Smaller xap file: SocketPro adapter for Silverlight is a very small dll (SAdapterForSilverlight.dll) having less than 16 kilo bytes only. If you use others, the referenced dlls will be much larger. The smaller library (SAdapterForSilverlight.dll) will speed up page loading on browser.
  • Out-of-Browser supported: SocketPro adapter for Silverlight fully supports Silverlight 4 out-of-browser feature.
  • Generics supported with SocketPro adapter for Silverlight: As shown in the above section, CRequest fully supports .NET generics. .NET generics is not supported with WCF at all.

5.    Further readings

6.    FAQs

    a.    Does SocketPro adapter for Silverlight supports SSL/TLS for secure communication?
    Yes! Both client and server sides are well supported on SSL/TLS for secure communication with SocketPro.

    b.    Can I use other HTTP servers but SocketPro server as a COMET server? If so, how can I do it?
    Yes! Theoretically you can use any other HTTP servers for processing your HTTP requests and use SocketPro HTTP server as push server. This is already shown in this article. Practically, it is already well supported with asp.net/AJAX because we have a class to simplify such an integration. For other HTTP servers, you can do the same once you understand communication data format with a little extra work. In the future, we'll provide code to assist you for such an integration. At this time, we can provide you free assistance for this purpose.