Push technology, or server push, is a style of Internet-based communication where the request for a given transaction is initiated by the publisher or central server. It is contrasted with pull/get, where the request for the transmission of information is initiated by the receiver or client.

Push services are often based on information preferences expressed in advance. This is called a publish/subscribe model. A client “subscribes” to various information “channels” provided by a server; whenever new content is available on one of those channels, the server pushes that information out to the client.

Push is sometimes emulated with a polling technique, particularly under circumstances where a real push is not possible, such as sites with security policies that require rejection of incoming HTTP/S requests.

Synchronous conferencing and instant messaging are typical examples of push services. Chat messages and sometimes files are pushed to the user as soon as they are received by the messaging service. Both decentralised peer-to-peer programs (such as WASTE) and centralised programs (such as IRC or XMPP) allow pushing files, which means the sender initiates the data transfer rather than the recipient.

Email may also be a push system: The SMTP protocol is a push protocol (see Push e-mail). However, the last step—from mail server to desktop computer—typically uses a pull protocol like POP3 or IMAP. Modern e-mail clients make this step seem instantaneous by repeatedly polling the mail server, frequently checking it for new mail. The IMAP protocol includes the IDLE command, which allows the server to tell the client when new messages arrive. The original BlackBerry was the first popular example of push-email in a wireless context.

Other uses of push-enabled web applications include market data distribution (stock tickers), online chat/messaging systems (webchat), auctions, online betting and gaming, sport results, monitoring consoles, and sensor network monitoring.

Now let’s see how the Push Technology evolved. Let’s start with having a look at the regular HTTP mechanism first:

Regular HTTP:

  • A client requests a webpage from a server.
  • The server calculates the response
  • The server sends the response to the client.

HTTP, by itself, does not give any support for any actual push mechanism as HTTP is a pure pull mechanism, which is user-initiated and server can never initiate a communication. Server can only send a response — either immediately or when the response is available if it becomes available before the set timeout — upon the request of the client. HTTP protocol cannot by itself provide a bi-directional full duplex communication where both client and server can send and receive each other’s messages at the exact same time like, for example, a telephone system, where the people at both ends can talk and hear at the same time.

1. Ajax Polling:

  • A client requests a webpage from a server using regular HTTP (see Regular HTTP portion).
  • The client receives the requested webpage and executes the JavaScript on the page which requests a file from the server at regular intervals (e.g. 0.5 seconds).
  • The server calculates each response and sends it back, just like normal HTTP traffic.

2. Long-Polling:

Long polling is itself not a true push; long polling is a variation of the traditional polling technique, but it allows emulating a push mechanism under circumstances where a real push is not possible, such as sites with security policies that require rejection of incoming HTTP/S Requests.

With long polling, the client requests information from the server exactly as in normal polling, but with the expectation the server may not respond immediately. If the server has no new information for the client when the poll is received, instead of sending an empty response, the server holds the request open and waits for response information to become available. Once it does have new information, the server immediately sends an HTTP/S response to the client, completing the open HTTP/S Request. Upon receipt of the server response, the client often immediately issues another server request. In this way the usual response latency (the time between when the information first becomes available and the next client request) otherwise associated with polling clients is eliminated.

For example, BOSH is a popular, long-lived HTTP technique used as a long-polling alternative to a continuous TCP connection when such a connection is difficult or impossible to employ directly (e.g., in a web browser); it is also an underlying technology in the XMPP, which Apple uses for its iCloud push support.

2.1. BOSH:

Bidirectional-streams Over Synchronous HTTP or BOSH is a transport protocol that emulates a bidirectional stream between two entities (such as a client and a server) by using multiple synchronous HTTP request/response pairs without requiring the use of polling or asynchronous chunking.

For applications that require both “push” and “pull” communications, BOSH is significantly more bandwidth-efficient and responsive than most other bidirectional HTTP-based transport protocols and AJAX. BOSH achieves this by avoiding HTTP polling, yet it does so without resorting to chunked HTTP responses as is done in the technique known as Comet. To date, BOSH has been used mainly as a transport for traffic exchanged between Jabber/XMPPclients and servers (e.g., to facilitate connections from web clients and from mobile clients on intermittent networks).

For “push”, a BOSH client starts an HTTP request, but the server postpones sending a reply until it has data to send. After receiving a reply, the client immediately makes another request on the same HTTP connection, so the server can always send data to the client without waiting for the client to poll. If, while waiting for a reply, the client needs to send data to the server, it opens a second HTTP connection. There are at most two HTTP connections open at a time, one on which the server can send data as a reply and one on which the client can send data as a POST.

“Bidirectional-streams Over Synchronous HTTP (BOSH)” and “XMPP over BOSH” are draft standards of the XMPP Standards Foundation.

The second related standard XMPP Over BOSH (XEP-0206) defines how BOSH may be used to transport XMPP stanzas. The result is an HTTP binding for XMPP communications that is intended to be used in situations where a device or client is unable to maintain a long-lived TCP connection to an XMPP server.

Mechanism of Long Polling:
  • A client requests a webpage from a server using regular HTTP (see Regular HTTP diagram).
  • The client receives the requested webpage and executes the JavaScript on the page which requests a file from the server.
  • The server does not immediately respond with the requested information but waits until there’s new information available.
  • When there’s new information available, the server responds with the new information.
  • The client receives the new information and immediately sends another request to the server, re-starting the process.

Let’s now examine in details how Long Polling differs from Ajax Polling:

AJAX Polling is for the application to poll the server continuously for any new data. If there is new data, then that is sent to the client, generally, via AJAX. This is similar to the way some children troll their parents by asking “Are we there yet?” every few seconds when riding in the car with their parents. Much to the parents’ chagrin, they have to answer ‘no’ continuously every few seconds until they finally reach their destination. Polling is just like that, where the application is basically asking whether there is new data after regular intervals of time and the server has to respond back every time, even if there is no new data to give.

Long Polling is a variation of the AJAX Polling but instead of the server giving an ‘empty’ response and closing the connection when it has no new data to give, the connection between client and server is kept open (with a timeout period). At some point in the future when the server does have some new data to give, it is given to the client and the connection is closed (provided it does so within the timeout period). This is better than polling in most ways, but if you try to use this approach in applications where a lot of data is generated very fast, then it becomes almost like the polling technique.

3. Comet:

Comet is a collection of techniques prior to HTML5 which use streaming and long-polling to achieve real time applications.

Comet is a web application model in which a long-held HTTPS request allows a web server to push data to a browser, without the browser explicitly requesting it. Comet is an umbrella term, encompassing multiple techniques for achieving this interaction. All these methods rely on features included by default in browsers, such as JavaScript, rather than on non-default plugins. The Comet approach differs from the original model of the web, in which a browser requests a complete web page at a time.

The use of Comet techniques in web development predates the use of the word Comet as a neologism for the collective techniques. Comet is known by several other names, including Ajax Push, Reverse Ajax, Two-way-web, HTTP Streaming, and HTTP server push among others.

Specific methods of implementing Comet fall into two major categories: Streaming and Long Polling.

Streaming:

An application using streaming Comet opens a single persistent connection from the client browser to the server for all Comet events. These events are incrementally handled and interpreted on the client side every time the server sends a new event, with neither side closing the connection.

Specific techniques for accomplishing streaming Comet include the following:

  • Hidden iframe
    A basic technique for dynamic web application is to use a hidden iframe HTML element (an inline frame, which allows a website to embed one HTML document inside another). This invisible iframe is sent as a chunked block, which implicitly declares it as infinitely long (sometimes called “forever frame”). As events occur, the iframe is gradually filled with script tags, containing JavaScript to be executed in the browser. Because browsers render HTML pages incrementally, each script tag is executed as it is received. Some browsers require a specific minimum document size before parsing and execution is started, which can be obtained by initially sending 1–2 kB of padding spaces.
    One benefit of the iframe method is that it works in every common browser. Two downsides of this technique are the lack of a reliable error handling method, and the impossibility of tracking the state of the request calling process.
  • XMLHttpRequest
    The XMLHttpRequest (XHR) object, a tool used by Ajax applications for browser–server communication, can also be pressed into service for server–browser Comet messaging by generating a custom data format for an XHR response, and parsing out each event using browser-side JavaScript; relying only on the browser firing the onreadystatechange callback each time it receives new data.
Ajax with long polling:

None of the above streaming transports work across all modern browsers without negative side-effects. This forces Comet developers to implement several complex streaming transports, switching between them depending on the browser. Consequently, many Comet applications use long polling, which is easier to implement on the browser side, and works, at minimum, in every browser that supports XHR. As the name suggests, long polling requires the client to poll the server for an event (or set of events). The browser makes an Ajax-style request to the server, which is kept open until the server has new data to send to the browser, which is sent to the browser in a complete response. The browser initiates a new long polling request in order to obtain subsequent events. Specific technologies for accomplishing long-polling include the following:

  • XMLHttpRequest Long Polling:
    For the most part, XMLHttpRequest long polling works like any standard use of XHR. The browser makes an asynchronous request of the server, which may wait for data to be available before responding. The response can contain encoded data (typically XML or JSON) or Javascript to be executed by the client. At the end of the processing of the response, the browser creates and sends another XHR, to await the next event. Thus the browser always keeps a request outstanding with the server, to be answered as each event occurs.
  • Script Tag Long Polling:
    While any Comet transport can be made to work across subdomains, none of the above transports can be used across different second-level domains (SLDs), due to browser security policies designed to prevent cross-site scripting attacks. That is, if the main web page is served from one SLD, and the Comet server is located at another SLD (which does not have cross-origin resource sharing enabled), Comet events cannot be used to modify the HTML and DOM of the main page, using those transports. This problem can be sidestepped by creating a proxy server in front of one or both sources, making them appear to originate from the same domain. However, this is often undesirable for complexity or performance reasons.
    Unlike iframes or XMLHttpRequest objects, script tags can be pointed at any URI, and JavaScript code in the response will be executed in the current HTML document. This creates a potential security risk for both servers involved, though the risk to the data provider (in our case, the Comet server) can be avoided using JSONP.
    A long-polling Comet transport can be created by dynamically creating script elements, and setting their source to the location of the Comet server, which then sends back JavaScript (or JSONP) with some event as its payload. Each time the script request is completed, the browser opens a new one, just as in the XHR long polling case. This method has the advantage of being cross-browser while still allowing cross-domain implementations.

4. HTML5 Server Sent Events (SSE) / EventSource:

Under SSEs the client establishes a persistent and long-term connection with the server. The server uses this connection to send data to a client. If the client wants to send data to the server, it would require the use of another technology/protocol to do so.

  • A client requests a webpage from a server using regular HTTP (see HTTP above).
  • The client receives the requested webpage and executes the JavaScript on the page which opens a connection to the server.
  • The server sends an event to the client when there’s new information available.
    • Real-time traffic from server to client, mostly that’s what you’ll need
    • You’ll want to use a server that has an event loop
    • Not possible to connect with a server from another domain

SSEs are best when we need real-time traffic from the server to the client or if the server is generating data in a loop and will be sending multiple events to the client.

Developing a web application that uses server-sent events is easier than with websockets. You’ll need a bit of code on the server to stream events to the front-end, but the client side code works almost identically to handling any other event.

Receiving events from the server:

The server-sent event API is contained in the EventSource interface; to open a connection to the server to begin receiving events from it, create a new EventSource object with the URL of a script that generates the events. For example:


    const evtSource = new EventSource("ssedemo.php");
        

If the event generator script is hosted on a different origin, a new EventSource object should be created with both the URL and an options dictionary. For example, assuming the client script is on example.com:


        const evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true } );

Once you’ve instantiated your event source, you can begin listening for messages from the server by attaching a handler for the message event:


evtSource.onmessage = function(event) {
  const newElement = document.createElement("li");
  const eventList = document.getElementById("list");

  newElement.innerHTML = "message: " + event.data;
  eventList.appendChild(newElement);
}

This code listens for incoming messages (that is, notices from the server that do not have an event field on them) and appends the message text to a list in the document’s HTML.
You can also listen for events with addEventListener():


evtSource.addEventListener("ping", function(event) {
  const newElement = document.createElement("li");
  const time = JSON.parse(event.data).time;
  newElement.innerHTML = "ping at " + time;
  eventList.appendChild(newElement);
});

This code is similar, except that it will be called automatically whenever the server sends a message with the event field set to “ping”; it then parses the JSON in the data field and outputs that information.


Sending events from the server:

The server-side script that sends events needs to respond using the MIME type text/event-stream. Each notification is sent as a block of text terminated by a pair of newlines. For details on the format of the event stream, see Event stream format.

The PHP code for the example we’re using here follows:


date_default_timezone_set("America/New_York");
header("Cache-Control: no-cache");
header("Content-Type: text/event-stream\n\n");

$counter = rand(1, 10);
while (true) {
  // Every second, send a "ping" event.
  
  echo "event: ping\n";
  $curDate = date(DATE_ISO8601);
  echo 'data: {"time": "' . $curDate . '"}';
  echo "\n\n";
  
  // Send a simple message at random intervals.
  
  $counter--;
  
  if (!$counter) {
    echo 'data: This is a message at time ' . $curDate . "\n\n";
    $counter = rand(1, 10);
  }
  
  ob_end_flush();
  flush();
  sleep(1);
}

The code above generates an event every second, with the event type “ping”. Each event’s data is a JSON object containing the ISO 8601 timestamp corresponding to the time at which the event was generated. At random intervals, a simple message (with no event type) is sent.

Note: You can find a full example that uses the code shown in this article on GitHub — see Simple SSE demo using PHP.


Error Handling:

When problems occur (such as a network timeout or issues pertaining to access control), an error event is generated. You can take action on this programmatically by implementing the onerror callback on the EventSource object:


evtSource.onerror = function(err) {
  console.error("EventSource failed:", err);
};

Closing event streams


By default, if the connection between the client and server closes, the connection is reset. The connection is terminated with the .close() method.

evtSource.close();
    


Event stream format



The event stream is a simple stream of text data which must be encoded using UTF-8. Messages in the event stream are separated by a pair of newline characters. A colon as the first character of a line is in essence a comment, and is ignored.

Note: The comment line can be used to prevent connections from timing out; a server can send a comment periodically to keep the connection alive.

Each message consists of one or more lines of text listing the fields for that message. Each field is represented by the field name, followed by a colon, followed by the text data for that field’s value.

Fields

Each message received has some combination of the following fields, one per line:
  • event
    A string identifying the type of event described. If this is specified, an event will be dispatched on the browser to the listener for the specified event name; the website source code should use addEventListener() to listen for named events. The onmessage handler is called if no event name is specified for a message.

  • data
    The data field for the message. When the EventSource receives multiple consecutive lines that begin with data:, it will concatenate them, inserting a newline character between each one. Trailing newlines are removed.

  • id
    The event ID to set the EventSource object’s last event ID value.

  • retry
    The reconnection time to use when attempting to send the event. This must be an integer, specifying the reconnection time in milliseconds. If a non-integer value is specified, the field is ignored.

All other field names are ignored.

Note: If a line doesn’t contain a colon, the entire line is treated as the field name with an empty value string.

Examples:


Data-only messages:
In the following example, there are three messages sent. The first is just a comment, since it starts with a colon character. As mentioned previously, this can be useful as a keep-alive if messages may not be sent regularly. The second message contains a data field with the value “some text”. The third message contains a data field with the value “another message\nwith two lines”. Note the newline special character in the value.

: this is a test stream

data: some text

data: another message
data: with two lines



Named events:
This example sends some named events. Each has an event name specified by the event field, and a data field whose value is an appropriate JSON string with the data needed for the client to act on the event. The data field could, of course, have any string data; it doesn’t have to be JSON.

event: userconnect
data: {"username": "bobby", "time": "02:33:48"}

event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}

event: userdisconnect
data: {"username": "bobby", "time": "02:34:23"}

event: usermessage
data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}



Mixing and Matching:
You don’t have to use just unnamed messages or typed events; you can mix them together in a single event stream.

event: userconnect
data: {"username": "bobby", "time": "02:33:48"}

data: Here's a system message of some kind that will get used
data: to accomplish some task.

event: usermessage
data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}



5. HTML5 Websockets:

  • A client requests a webpage from a server using regular http (see HTTP above).
  • The client receives the requested webpage and executes the JavaScript on the page which opens a connection with the server.
  • The server and the client can now send each other messages when new data (on either side) is available.
    • Real-time traffic from the server to the client and from the client to the server
    • You’ll want to use a server that has an event loop
    • With WebSockets it is possible to connect with a server from another domain.
    • It is also possible to use a third party hosted websocket server, for example Pusher. This way you’ll only have to implement the client side, which is very easy!
  • Some libraries to use WebSocket to develop a realtime app :



Web Socket is discussed in details here.

Some of the above mentioned technologies are widely used to create real-time services like chat application. In .NET, SignalR is a great technology to implement some of these push technologies. SignalR primarily uses WebSocket, but it later fallbacks to Long Polling and/or Server Sent Events (SSEs) as need be and based on availability. Not all browsers support SSE.

Related Chapter:





The above content is written by:

Abhishek Dey

Abhishek Dey

A Visionary Software Engineer With A Mission To Empower Every Person & Every Organization On The Planet To Achieve More

Microsoft | University of Florida

View LinkedIn profile


If you have any feedback, please use this form: https://thealgorists.com/Feedback.




Subscribe to Our Youtube Channel

Follow Us On LinkedIn
wave