Home Products Consulting Download Registration Support Events

Home
Up

Send Instant Web or Window Messages through SocketPro HTTP Server Push

        UDAParts
        support@udaparts.com
        Updated on 05/16/2009

Contents

Introduction

    Browser-based instant message is a HTTP advance topic. It is particularly useful to get a team of people or web clients through browsers for cooperation in real-time fashion. There are many such examples like stock market data distribution, online web chat, online auction, online betting, online gaming, and so on. All these samples require data pushed from a HTTP server onto browsers in a very short time. However, it is considerably difficult to get web instant messages through HTTP protocol because the protocol is not designed with server push in mind at all. Therefore, you can not easily see real-time web notification with a publish/subscribe mode. Recently, we have upgraded our SocketPro with not only basic HTTP service but also HTTP server push support, and wish HTTP server push become much easier for you.

    This short article guides you to quickly develop a message push system through SocketPro, which enables you to send messages among web browsers, devices, window desktop and server applications.

SocketPro Implementation to HTTP Server Push

    After having investigated many technologies, UDAParts selects long-time polling approach to implement SocketPro HTTP server push. With long polling, a client initially sends a request to a SocketPro server enabled with HTTP service in a similar way to a normal polling. However, the server wait until an available message or a long time timeout. Once a message or time out comes from a SocketPro server to a web browser client, the client will re-send a new request until the next message or timeout. By this way, a SocketPro server will almost always have an available waiting request so that it can immediately deliver a message from server to client in response to an event. This approach also enables a callback from a SocketPro server to a client through HTTP service.

    SocketPro supports both the same-domain and cross-domain (or cross site) HTTP server pushes. SocketPro is relied on AJAX for the same-domain HTTP server push and JavaScript tag for cross-domain server push. On server side, the core library (usktpror.dll) has implemented a set of HTTP functions for HTTP server push. To make use of HTTP server push easier, we have just updated our SocketPro adapters for .NET and JavaScript so that you can realize HTTP server push effortless in a few hours through our SocketPro in the successive sections.

   Further, UDAParts has successfully integrated HTTP server push with our original built-in chat service so that you can send a message from a desktop or device application to a web application, and vice versa. We'll use some old sample applications to show you this integration.

Pre-requirements and Preparation

    As described in the previous tutorial, you should have a basic knowledge about HTTP although you are not required to know all of HTTP details. If you don't know HTTP, please use Google or Yahoo search engine to search for key words like 'HTTP protocol tutorial'.

    This tutorial (chat) tells you how to use SocketPro HTTP server push. After compiling one of the tutorial samples inside the directory ..\udaparts\socketpro\tutorial, you need to copy the files inside the directory ..\udaparts\socketpro\tutorial\HTTPChatSampleFiles into the directory of your compiled exe application. These files are used for testing. Note that there is no client sample application provided for this HTTP tutorial, but the client test application is your browser, FireFox, IE, Safari, Opera, Flock or else. There are extra sample files shared for Silverlight push demonstration as shown in this article.

    If you follow the above instructions correctly, you are expected the following picture.

   

    We would like you to use FireFox plus free plug-in FireBug. FireBug is the best free web browser debug tool available at this writing time. You can use the tool to debug HTTP transaction between browser and sample SocketPro on client side so that you can see how UDAParts SocketPro adapter (ujsonxml.js) works. It may require you to have some basic knowledge about JavaScript.

    This tutorial requires you a simple understanding about JSON. In case you don't know JSON, please go to the site www.json.org. Now, SocketPro adapter for JavaScript contains a JSON JavaScript object, named as UJSON. 

    After successfully compiling the tutorial and running the SocketPro server, you can play it from a browser. See the below sample picture.

   

The First Step to SocketPro HTTP/Binary Push

    The sample project is located at the directory of C:\Program Files\UDAParts\SocketPro\tutorial\CSharp (VBNet)\Chat\Server.

    To enable SocketPro HTTP/binary push is to make a few calls for configuration so that SocketPro knows how to handle various chat requests. First of all, you need to create a set of chat groups. Within SocketPro, you can push a message onto one or multiple groups of clients. To do so, create a few chat groups using the below code snippet.

            bool bSuc;

            bSuc = PushManager.AddAChatGroup(1, "Group for SOne");

            bSuc = PushManager.AddAChatGroup(2, "DB Service");

            bSuc = PushManager.AddAChatGroup(4, "Management Department");

            bSuc = PushManager.AddAChatGroup(6, "R&D Development");

            bSuc = PushManager.AddAChatGroup(8, "IT Department");

            bSuc = PushManager.AddAChatGroup(16, "Sales Department");

    The above code snippet creates five chat groups with group identification numbers, 1, 2, 4, 8, and 16. The group id number can be any number except zero. 

    After you complete the above calls, it is ready for SocketPro to handle various chat calls from either client or server side without using HTTP or independent chat service. Note that all of other services internally inherits the chat service. You can think the chat service as a base class. However, we'll use both the chat and HTTP services in this tutorial so that we have to enable them in SocketPro. Note that the two services are SocketPro built-in services. To enable them, you'd make below calls:

            private CSocketProService<CHttpPeer> m_HttpSvs = new CSocketProService<CHttpPeer>();

            private CNotificationService m_ChatSvs = new CNotificationService();
        

            // ......
        

            //sidHTTP = 266

            bSuc = m_HttpSvs.AddMe((int)USOCKETLib.tagServiceID.sidHTTP, 0, tagThreadApartment.taNone); //enable HTTP service

            bSuc = m_HttpSvs.AddSlowRequest((short)USOCKETLib.tagHttpRequestID.idGet);

            bSuc = m_HttpSvs.AddSlowRequest((short)USOCKETLib.tagHttpRequestID.idPost);
        

            //sidChat = 257

            bSuc = m_ChatSvs.AddMe((int)USOCKETLib.tagServiceID.sidChat, 0, tagThreadApartment.taNone); //enable independent chat  service

    In the above we create two instances of services first, one for HTTP service and the other for independent chat service. Afterwards, we enable HTTP service, and use a worker thread in pool to process HTTP GET and POST commands. Finally, we make a call to enable independent chat service.

Coding for HTTP Push on Server Side

    First of all, you need to derive a sub class from the class CHttpPushBase. The second step is to override the virtual function either OnFastRequestArrive or OnSlowRequestArrive, depending on if you use a worker thread to process HTTP GET or POST command. We use a worker thread to process the two commands, as shown in the above code snippet. Inside the function, you may need to solve a browser-related problem as shown in the below code, although SocketPro adapter tries its best to hide browser-related problems as many as possible.

 

        protected override int OnSlowRequestArrive(short sRequestID, int nLen){

/*

SocketPro tries to hide browser-related problems as many as possible. However,

you may still use the below code to solve a problem that SocketPro does not handle well

usually by setting a proper response header.

                */

        

//http://www.useragentstring.com/pages/useragentstring.php

                string strUserAgent = Headers["User-Agent"].ToLower();

if(strUserAgent.IndexOf("msie") != -1)

        SetResponseHeader("Connection", "close");

                Console.WriteLine("BrowserIpAddress = " + BrowserIpAddress + ", data = " + Query);

return base.OnSlowRequestArrive(sRequestID, nLen);

        }

    To understand the above HTTP transaction between browser and SocketPro server, you'd start the browser FireFox, and use the debug tool FireBug as shown in the below picture.

   

    If you like to see how code execution with more details on server side, you can override the virtual functions IsOk as shown in this sample, OnBeforeProcessingHttpPushRequest and OnAfterProcessingHttpPushRequest. However, it is not so important now because the class CHttpPushBase has already hidden all of HTTP server push pitfalls for you. If you like to track the exception during processing HTTP request, you can override the virtual function OnProcessingHttpPushRequestException.

SocketPro Adapter for Web Browser

    To make HTTP push easier on web browser side, we provide an adapter for web browsers through JavaScript. At this time, SocketProAdapter for JavaScript uses JSON data format for serializing objects and method parameters into a large string before sending it onto a remote SocketPro HTTP push server.

    Now, it is time to have a close look at the sample html file httppush.htm, and see how simple it is on client side.

    First, refer the file ujsonxml.js for SocketProAdapter for JavaScript as shown in the below. Note that this file should be located at SocketPro HTTP push server. SocketPro HTTP server push reads the file and sets all of necessary configuration settings for you at run time.

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

    SocketPro adapter for web browsers makes calling your HTTP requests really simple. As an example, here is a sample code.

            function btnSpeak_onclick() {

                    var chatGroups = document.getElementById('txtGroups').value.split(',');  //chatGroups is array of ids like [1,2,3]

                    var req = UChat.speak(document.getElementById('txtMsgOut').value, chatGroups);

            }

 

    The above code shows how to send a message onto a set of chat groups of clients. All of other calls for enter, sendUserMessage, exit and listen (or subscribe) are similar. For details, see the file httppush.htm.

    To track the returning results and push messages from other clients, we must set a callback. To do so, we need to set the property onMessage on the JavaScript object UChat as shown in the below code snippet.

        UChat.onMessage = function onMessage(req, msg) {

                 //Use UJSON to convert a JavaScript object (msg) into a string

                document.getElementById('txtMsgIn').value = UJSON.stringify(msg);

                switch (req.method) {

                case 'exit':

                        myInit();

                        break;

                case 'enter':

                        if (UChat.chatting()) {

                                document.getElementById("btnSendUserMessage").disabled = '';

                                document.getElementById("btnSpeak").disabled = '';

                                document.getElementById("btnSubscribe").disabled = 'disabled';

                        }

                        break;

                default:

                        break;

                }

        };

     It can not be simpler further! SocketProAdapter for JavaScript hides all of details for you with both same and cross domain communication on client side too.

    SocketProAdapter HTTP request object:    In case you like to send requests other than HTTP push-related requests, you can use the below code snippet from the file C:\Program Files\UDAParts\SocketPro\tutorial\HTTPServiceSampleFiles\udemo.htm.

        var req;

        function btnSend_onclick() {

                if(!req)

                        req = UHTTP.createRequest(     'echo', //required, request name

                                                                                  0); //optional, 0, false (default) json, 1 -- xml

 

                var firstName = document.getElementById('txtFirstName').value;

                var lastName = document.getElementById('txtLastName').value;

                var age = document.getElementById('txtAge').value;

 

                req.clear(); //remove previously stored parameters

 

                //add the 1st parameter and its value

                req.add('firstName', firstName);

 

                //add the 2nd parameter and its value

                req.add("lastName", lastName);

 

                req.add('age', age);

 

                //send request, and it returns a unique request index which may be useful later

                var index = req.invoke(   myCallback, //required, a callback function to handle returning data

                                                            0, //optional, 0, false (default) POST, 1 -- GET

                                                            0 //optional, 0, false (default) async, 1 -- sync

                                        );

        }

        Here myCallback function is defined as the below.

        function myCallback(req, data){

                //you may parse your result here .....

                var obj = UJSON.parse(data);

                document.getElementById('txtResult').value = data;

        }

     By this way, you can easily create a request object and send any number of parameters onto a remote SocketPro server with HTTP service enabled.

    The below picture shows SocketPro HTTP request object.

   

    As shown from the picture, SocketPro adapter HTTP request object clearly has two properties, method and config. The method abort is used for aborting a HTTP response. The method add, as shown previously, is used for constructing an object dynamically. In case you like to re-use an existing request object, you need the method clear to remove previous parameters and their values. The method getCallIndex is used to retrieve a unique integer call index. The method getCallback is used to retrieve callback set previously. The method getScript is used to retrieve either an AJAX object for same-domain or a JavaScript tag object for cross-domain.

    The method invoke is used to send a real HTTP request onto a SocketPro server enabled with HTTP service.

            /*

            invoke a request from browser to a web server.

 

            1.     cb -- required callback handler.

            2.     isGet -- default to POST. 1 or true for GET

            3.     sync -- default to asynchronous processing, and 1 or true for synchronous processing.

            */

            me.invoke = function(cb, isGet, sync) {

                    if (!me.method && typeof (me.method) != 'string')

                            throw new Error(500, "HTTP: request name not specified properly!");

                    if (typeof (cb) != 'function')

                            throw new Error(500, "HTTP: callback function not specified properly!");

                    if (!me.isCompleted())

                            throw new Error(500, "HTTP: previous request not completed yet!");

                    cIndex = ++callIndex;

                    callback = cb;

                    doCall(isGet, sync);

                    return callIndex;

            };

    The method isCompleted is used to check if a request is processed and its HTTP response has come. The method isCrossSite is used to check if a request is cross-domain one.

    All of these methods should not be too difficult for you to understand and use. We have tested libraries against multiple browsers and should work with all of major browsers on cross platforms.

Integration SocketPro COMET with Devices and Normal Desktop/Server Applications

    We have integrated HTTP server push with device and normal desktop/server applications. See the below picture for device from the project DevTest inside the directory of ..\udaparts\SocketPro\samples\device\samplesCE\DevTest, which is written from Visual C++ 4 for smart devices.

   

    It is also simple to communicate with other desktop or server application using push through SocketPro chat service. See the below sample application which was written from old VB6 long long time ago, which can be found inside the directory of ..\udaparts\SocketPro\samples\others\client\vb6\chatTest.

   

    You can use the tutorial two to test integration with HTTP server push.

Integration your HTTP servers with SocketPro COMET server

    This tutorial sample server is not only a simple HTTP server but also a comet server. In many cases, you may like to separate a HTTP server from a comet sever. For example, you may use MS IIS or apache as a HTTP server on a machine, and our SocketPro comet server on another machine for push only. Therefore, we provide an extra sample to support such an architecture. You can find the sample HTTP push at the directory C:\Program Files\UDAParts\SocketPro\samples\HTTPChat\csharp (vbnet). The sample is almost the same as this tutorial. Once understanding this tutorial sample, you are expected to understand this sample without any problem at all.

    SocketProAdapter for .NET has a very simple sealed class AspNetPush inside the namespace SocketProAdapter.ClientSide. The class exposes one static property pointing to an interface IComet implementation on Asp.NET side. You can use the interface to manage accessing HTTP server push through Asp.NET. See the below sample snippet code.

        protected void Page_Load(object sender, EventArgs e){

                if (AspNetPush.Comet.UrlToComet.Length == 0){

                        //make sure you have already started the HTTP COMET server at

                        //C:\Program Files\UDAParts\SocketPro\tutorial\CSharp\Chat\Server

                        AspNetPush.Comet.UrlToComet = "http://localhost:20901/UCHAT";

                }

        }

    As you can see, you need to set a URL address to a SocketPro HTTP comet at the very beginning. Later, we can call the method IComet.Enter as shown in the following.

        protected void btnEnter_Click(object sender, EventArgs e){

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

                string strEnter = AspNetPush.Comet.Enter(this, txtUserId.Text,  groups, "onMyMessage");

                btnEnter.Enabled = false;

        }

    Once the method Enter returns an expected result with a chat id, SocketPro internally registers a JavaScript client block on a page as shown in the below.

     <script type='text/javascript' src='http://idtye:20901/ujsonxml.js'></script>

    Also, SocketPro automatically inserts a JavaScript client block right before the end of tag form.

  <script type='text/javascript'>UHTTP.defaultConfig.chatId='{FE336BCF-5A2C-41B5-97A6-0DCFEAA31AF3}';UChat.onMessage=onMyMessage;UChat.subscribe(150);</script>

    Limit accessing SocketPro HTTP push for better security from your server code:    Sometimes, we don't want every one on the earth is able to access our HTTP server push service. To make security better, we can limit accessing our HTTP server push service to permitted persons. To do so, we need to override the virtual function IsOK of the class CHttpPushBase using the following code snippet.

        protected override bool IsOk(Dictionary<String, object> parameters){

                int nPort = 0;

                string strIpAddress = GetPeerName(ref nPort);

                //control clients from a list of allowed ip addresses.

                //especially useful for cross-domain HTTP Push.

                //return (m_lstAllowIpAddress.IndexOf(strIpAddress) != -1);

                return true; //true permitted, false denied

        }

Further readings

FAQs

  1. Your tutorial sample is written for HTTP. Does SocketPro HTTP push support secured transaction through SSL or TLS?
    Yes! It should not give you any problem at all.
            
  2. I have heard that HTTP push scalability is usually poor because most of major HTTP server is not created with HTTP push in mind. How do you solve this problem?
    SocketPro HTTP server is highly scalable because it is written from 100% non-block communication in mind. This special design leads much less number of threads required on server side. Also, SocketPro HTTP service is much lighter. Our experiment result shows that a SocketPro HTTP COMET server is able to easily support 10,000 push connections on one typical server at the same time.
            
  3. Can I write my own code from my own applications instead of browsers to subscribe for SocketPro HTTP push events?
    Of course! As described from this tutorial, you need to create two instances of HTTP requests. One is for sending request, and the other for waiting for available messages or a timeout.
            
  4. I saw this site. Should I use this HTTP server push technology or that one?
    That technology is dependent on plug-in for Mozilla browsers and activeX control for IE. It is completely dependent on the client core library npUSocket.dll. Therefore, you probably do not like that approach because it lacks probabilities of integration with other platforms or development languages. Also, you can distribute that dll with your applications on MS window platforms only. Therefore, its usage is limited. If you use our HTTP server push, there are no such problems. However, HTTP server push technology is slower with a limited number of features because of HTTP restrictions. If you use plug-in approach, it will be much faster with many more powerful features like requests batching, online compression/de-compression, and both asynchronous and synchronous computation as well as others.
            
  5. How do you protect my SocketPro server from situations that my browsers crash, my client computers suddenly power off, or networks are dead for some unknown reasons?
    SocketPro core server library usktpror.dll has ways to transparently prevent these bad situations internally. You don't need coding anything for dealing with these bad situations at all. This is not a problem to SocketPro.