QNimate

  • CoursesVideos
  • WP PremiumPlugins
  • DemosLab
  • Home
  • QIdea
  • QTrack
Home Carbon Ads Push Technology In PHP

Push Technology In PHP

comet application model

Suppose you are planning to create applications like Facebook timeline, Gmail chat, live score viewer or instant chat and you are wondering how to send notification from server to the browser for updates instead browser requesting data from server after every constant interval then this post will help you learn the technologies that are used to send data from server to browser as soon as the update is available.


Push technology is a Internet based communication where server sends data to the client instead of client requesting data from the server.

Achieving Push technology using HTTP protocol in browsers is called as Comet Application Model.

There are many different ways of achieving push technology from web server. It can be achieved using default browser features (comet programming) or using external plugins. In this tutorial we will look at the ways of implementing push technology using comet application model.


Chunked Transfer Encoding

Before learning about implementing comet application model we need to learn about Chunked Transfer Encoding.

Chunked transfer encoding is a data transfer mechanism in HTTP version 1.1 in which data is sent in a series of “chunks”. It uses the Transfer-Encoding HTTP header instead of the Content-Length header. Because the Content-Length header is not used, the server does not need to know the length of the content before it starts transmitting a response to the receiver. Server can begin transmitting dynamically-generated content before knowing the total size of that content. The size of each chunk is sent right before the chunk itself so that the browser can tell when it has finished receiving data for that chunk. The data transfer is terminated by a final chunk of length zero.

Whenever we send data from server to client before script execution is completed(or file size is not confirmed), the web server sends the data as chunked. So when we use flush() the web server automatically adds the chunked transfer encoding headers and sends the data. Remember that browser starts executing the response content only after receiving 1kb of chunk data.

Chunked Transfer encoding headers are:

Content-Encoding: chunked
Transfer-Encoding: chunked

1. Hidden iFrame

Let’s see how an iFrame can be used to achieve push technology. An hidden iframe is embedded into the html page. The source of the iframe is received via chunked transfer encoding. So the server can infinitely send the source code of the iframe. So in this way the server can send JavaScript code to the iFrame whenever an update is available. As soon as a chunk of JavaScript code is received the browser starts executing it and the JavaScript code updates the user display.

Let’s see demo code for this:

index.html

<body>
   <iframe style="display: hidden" src="http://www.yourdomain.com/recieveData.php"></iframe>
   <span id="update"></span>
</body>

receieveData.php

<?php
         /*browser starts executing the received code only after receiving 1kb of chunk data. So we need to send 1kb data before we send real code for execution.*/
        $p = "";  //padding
        for ($i=0; $i < 1024; $i++) {
            $p .= " "; //we can send any character, here we are sending white space.
        };
        echo $p;

        ob_flush();
        flush();

        /*Now we will send update code to iframe whenever an update is available. Below code is just an example.*/
        for ($i = 0; $i < 10000; $i++) {
            ?>
              <script>
                 parent.document.getElementById("update").innerHTML = "<?php echo $i; ?>";
              </script>
            <?php
            ob_flush();
            flush();
            sleep(2);
        }

?>


2. Mixed-Replace

To understand this method we need to understand “Content-Type: multipart/x-mixed-replace” header in HTTP protocol.

Whenever we include this header in the HTTP response the browser interprets this as an changing document (prepares to receive new versions of this document) and keeps the connection alive. Whenever server sends an updated document, browser replaces the current document with the new document.

In this way server can send newer version of the document whenever update is available.

Let’s see demo code for this:

index.php

<?php
   $seperator = "jfdkjgieorgjijergoidsufy9asif"; //some random string used to separate the different versions of the document.
   header("Content-Type: multipart/x-mixed-replace; boundary=$seperator");

print "--$seperator\n";

$n = 0;
while($n < 10)
{
    print "Content-Type: text/plain\n\n";
    $n++;
    echo $n."This number will increment after 5 seconds.";
    print "\n--$seperator\n";
    ob_get_flush();
    flush();
    sleep(5);
}
?>

In this case also browser sends the data as chunked. Every chunk is interpreted as a new page by the browser.


3. Server Sent Events

Server sent events is a HTML5 API. In this method browser keeps the connection open if server responds with response type as “text/event-stream” for a request made using server sent events api.

To implement server sent events we need to create an event object and pass the url as the parameter. Whenever there is an update from server, browser fires the callback.

Server must send response type as “text/event-stream” which makes browser believe that server is responding to Server Sent Events API and keeps the connection open.

polling

This API is not available in Internet Explorer yet so be careful while using it.

Let’s see demo code for this:

index.html

<div id="update"></div>

<script>
  var sse=new EventSource("data.php");
  sse.onmessage=function(event)
  {
     document.getElementById("update").innerHTML+=event.data;
  };
</script>

data.php

<?php
header('Content-Type: text/event-stream'); //indicates that server is aware of server sent events
header('Cache-Control: no-cache');//disable caching of response

$x = 0;

while($x < 1000)
{
   $x++;
   echo "data: ".$x."\n\n"; //Always start output with "data: " and end with "\n\n" so that browser can parse and initialize the event.data variable.
   ob_get_flush();
    flush();
   sleep(10);
}
?>

Here web server is sending data as chunked. Here we are not sending 1kb of chunked data before actual data. Thats because we are interpreting the response not the browser.


4. Long Polling

In this method whenever client makes a request to the server for update, the server holds on the connection and provides response only when update is available. So every request from client results in receiving update from server. The response from the server is a complete response. And client initiates another request as soon as response is received.
polling

There are two ways of implementing long polling in web browser. We will look at both of them.

4.1. AJAX Long Polling

As the name suggests we initiate a HTTP connection to server using XMLHttpRequest object. And when browser receives complete response from server the callback is fired and status code changes to 200. And then we again initiate a new connection for new updates. In this way we always keep a connection open to the server.

Remember that we need to check if user is still online after every constant interval before sending the response. If we won’t check this then there is no way the server script will stop executing and therefore web server will be out of resources soon.

Let’s see demo code for this:

index.html

 <span id="update"></span>
<script>
function recieveData(){
  var ajaxObject = new XMLHttpRequest();
  ajaxObject.open("GET", "data.php");
  ajaxObject.onload = function(){
     if(ajaxObject.readyState == 4 || ajaxObject.status == 200)
     {
         document.getElementById("update").innerHTML = ajaxObject.responseText;
         recieveData();
     }
  }
  ajaxObject.send();
}
recieveData();
</script>

data.php

<?php
set_time_limit(0); //removes time limit for script execution
ignore_User_Abort(True); //disable automatic script exit if user disconnects. you can set it to false if you want the script to stop executing when user exits. But its better to exit the script manually if you want to save some data or make some other changes.

while(!connection_aborted())//this function checks if user is online.
{

    if(True)//here check if an update is available or not. If its available echo it and exit the script so that browser will recieve a complete response (status code 200)
    {
        echo "Update Found";
        ob_get_flush();
        flush();//if it sees that user is offline (fails to send response) then it terminates the script if ignore_User_About is not set to True. Here it will ignore the failed response as its set to True.
        exit;
    }
    else
    {
        sleep(1);//wait for 1 second before checking for update and finding out if user is online or not.
    }
}
?>

AJAX Long Polling also sends information as chunked. Here we are not sending 1kb of chunked data before actual data. Thats because we are interpreting the response not the browser. Only browser executes after 1kb of chuck data.

4.2. Script tag long polling

In this method we generate script tags dynamically. src attribute points to the web server push URL. Web server returns JavaScript code only when an update is available. As soon as the code is returned and executed an another script tag is generated dynamically. In this way tags are created and a connect is kept open to the server.

Use Script tag long polling instead of AJAX long polling only when you need updates from other subdomains. If you want to use AJAX long polling to make connections with subdomains then you need to create a proxy server emulating subdomains.

Let’s see demo of this:

index.html

<body id="myBody">

<span id="update"></span>
<script type="text/javascript">
function dynamicLoad()
{
    var script= document.createElement('script');
    script.type= 'text/javascript';
    script.src= 'data.php';
    document.getElementById("myBody").appendChild(script);
}
dynamicLoad();
</script>
</body>

data.php

<?php
set_time_limit(0); //removes time limit for script execution
ignore_User_Abort(True); //disable automatic script exit if user disconnects. you can set it to false if you want the script to stop executing when user exits. But its better to exit the script manually if you want to save some data or make some other changes.

while(!connection_aborted())//this function checks if user is online.
{

    if(True)//here check if an update is available or not. If its available echo it and exit the script so that browser will recieve a complete response (status code 200)
    {
        header('Content-Type: text/javascript');
         
        $x = "document.getElementById('update').innerHTML = document.getElementById('update').innerHTML +'1';";
        $x = $x . "setInterval(dynamicLoad,3000);";
        echo $x;
        ob_get_flush();
        flush();//if it sees that user is offline (fails to send response) then it only terminates the script if ignore_User_About is not set to True. Here it will ignore the failed response as its set to True.
        exit;
    }
    else
    {
        sleep(1);//wait for 1 second before checking for update and finding out if user is online or not.
    }
}
?>

Here also we are sending data as chunked. Here we are not sending 1kb of chunked data before actual data.


5. Pushlet

In this method when client makes request to a webpage, the server takes advantage of persistent HTTP connections, and leaves the connection open (i.e., the server never terminates the response), and it seems like browser is getting response from a slow server. Whenever update is available server sends response to the browser and browser executes the code.

This method doesn’t work well because some browsers have page load timeout set, which results in page refresh if server is taking too long to respond.

Let’s see demo of this:
index.php

<?php
set_time_limit(0);
ignore_User_Abort(True);
?>
<!doctype html>
<html>
<body>
    <span id="update"></span>


<?php
    $p = "";  //padding
    for ($i=0; $i < 1024; $i++) {
        $p .= " "; //we can send any character, here we are sending white space.
    };
    echo $p;

    ob_flush();
    flush();
    while(True)
    {
        ?>
        <script type="text/javascript">
            document.getElementById("update").innerHTML = "<?php echo time(); ?>";
        </script>
        <?php
            ob_flush();
            flush();
            sleep(3);
    }
?>


</body>
</html>

Here also we are sending information as chunked.


6. WebSocket API

WebSocket is a network protocol supported by all modern browsers. This protocol is specially designed for push technology so that client and server can send data to each other by just initiating connection once.

WebSocket API is the interface provided by the browser for WebSocket Protocol.

You need to have a WebSocket server for WebSocket API to work. You can build your own WebSocket Server using any programming language or you can install WebSocket plugins in supported HTTP Web Servers.

Using WebSocket API you can easily initiate a WebSocket connection to a WebSocket Server.

Let’s see a client side demo of this:

index.html

  var WebSocketObject = new WebSocket('ws://yourdomainname.com/data', ['soap', 'xmpp']);
  //you can use wss instead of ws for secure communication.

// connection open event
WebSocketObject.onopen = function () {
  WebSocketObject.send('Hello'); //sending message to server.
};

// error event
WebSocketObject.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

// update received from server event
WebSocketObject.onmessage = function (e) {
  console.log('Server: ' + e.data);
};

When we use WebSocket protocol to implement push technology then we don’t call it as comet programming as comet programming is term tightly associated with HTTP protocol.


Conclusion

We saw many ways by which we can implement push technology. Every method has some pros and cons. Hidden iFrame and Mixed-Replace keeps the main page loading which provides bad user experience. Server Sent Events are not supported by all browsers. WebSocket API is supported in new web browsers. To use websocket you need to have a websocket supporting server too. So the best solution is long polling as it is supported by all browsers and doesn’t require special server configurations like websocket API needs. “Like and Share”

Feb 4, 2014Narayan Prusty
How to get your picture in Google search resultsDecentralizing Configuration of Webserver using .htaccess
Comments: 2
  1. Jazz
    6 years ago

    Thanks for your tutorial..

    One question.. in the AJAX Long Polling example I notice that you have not included the header(‘Cache-Control: no-cache’); command.

    My understanding is that without this tag that the cache will store responses, and not give the user new data until the cache expires. Is there a reason this is not needed in this example, or should I add this in to my own implementation of the script?

    Thanks in advance

    ReplyCancel
  2. Shashi
    7 years ago

    Thanks for this tutorial. Very informative. I personally like the Long Polling examples.

    ReplyCancel

Leave a Reply Cancel reply

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Narayan Prusty

I am a software engineer specialising in Blockchain, DevOps and Go/JavaScript. This is my personal blog where I write about things that I learn and feel interesting to share.

Image9 years ago 3 Comments Web Developmentcomet programming, long polling, push technology
Share this
0
GooglePlus
0
Facebook
0
Twitter
0
Linkedin
  • Chunked Transfer Encoding
  • 1. Hidden iFrame
  • 2. Mixed-Replace
  • 3. Server Sent Events
  • 4. Long Polling
  • 5. Pushlet
  • 6. WebSocket API
Related Articles
  • URL Tracking Parameters and Its Negative Impact
  • Preventing CSRF Attacks In WordPress Using Nonces
  • Create a Intel XDK APP with PHP and MySQL Backend
  • Increase PHP Script Execution Time
  • HTTP/2 Compatibility with old Browsers and Servers
Our Sponsor
My Books

2014 - 2015 © QNimate
All tutorials MIT license