How to make all connected browsers reload initiated by a server-side event
Asked Answered
H

7

4

Suppose there is a webpage with dynamically generated content -- say a div containing the current number of connected browsers. When the count changes on the server I want all connected browsers to reload the count so that everyone sees the increment/decrement.

What's the best way to accomplish this?

Keywords: ajax, broadcast, browser, div, jquery

Hawsepipe answered 26/12, 2009 at 22:6 Comment(0)
H
3

Here's how to do server-push using ajax long-polling. The browser makes an ajax request which initiates server-side self-polling. The ajax request remains open, waiting for a response until the file changes, and as soon as it gets a response, it makes a new long-polling request.

Here's what it looks like with jQuery and php, implementing the example of live-updating a div in the html showing the number of clients currently connected:

index.html:

<html>
<head>
<title>Comet Test</title>
  <script type="text/javascript" src="jquery.js"></script>
  <script type="text/javascript" src="longpolling.js"></script>
</head>
<body>
  Number of connected users: <div id="total">0</div>
</body>
</html>

longpolling.js:

$(document).ready(function() { connectToServer(1); });

function connectToServer( incp ) {
  $.get("LongPolling.php",
        { inc: incp },
        function(resp) {
          $('#total').html(resp);
          connectToServer(0);
        }
       );
}

LongPolling.php:

<?php

# (over)write file with contents, locking the file while doing so.
# just barf and die if there's an error.
function update($file, $contents)
{
  $f = fopen($file, 'w');
  if(!$f) { echo "ERROR1"; exit; } # couldn't open file for writing.
  if(!flock($f, LOCK_EX)) { echo "ERROR2"; exit; } # couldn't get lock.
  fwrite($f, $contents);
  fclose($f);  # this also releases the lock.
  return $contents;
}

# fetch the contents of the given file.
# if the file doesn't exist, create it with contents "0"
function fetch($file)
{
  if(file_exists($file)) {
    if(!is_readable($file)) { echo "ERROR3"; exit; }
    $x = file_get_contents($file);
  } else {
    $x = 0;
    update($file, $x);
  }
  return $x;
}

$fc = 'connx.txt';   # file that stores the number of connections.

if ( $_REQUEST['inc'] == 1 ) {  # someone just connected.
  echo update($fc, fetch($fc)+1);
} else {  # someone is reconnecting (also happens immediately after connect).
  $last = filemtime($fc);
  do {  # wait until some other instance causes $fc to change...
    sleep(1);
    clearstatcache(); # otherwise filemtime() results are cached!
  } while(filemtime($fc) == $last);
  echo fetch($fc);
}
?>

NOTE: This does not track disconnects, so it's more like live-tracking the total number of pageviews. See Running server-side function as browser closes for info on keeping track of browser disconnects, ie, server-side action on client disconnect.

Hawsepipe answered 4/1, 2010 at 21:25 Comment(1)
This seems to work fine for me on Firefox but on Safari and Chrome it shows the little spinny icon forever and never thinks it's finished loading the page. Any idea what's going on there? (Should I make this a separate StackOverflow question?)Gilbertogilbertson
I
7

I think COMET might be what you're looking for. Web Sockets would be ideal but lack of browser adoption wouldn't make it practical right now.

Invaginate answered 26/12, 2009 at 22:11 Comment(1)
And there's a jQuery plugin for it described in this thread: https://mcmap.net/q/193248/-comet-and-jquery-closed/…Grane
E
5

HTTP protocol is stateless by design. The only one way to achieve this is to implement client-side polling via AJAX.

Ergocalciferol answered 26/12, 2009 at 22:10 Comment(0)
H
3

Here's how to do server-push using ajax long-polling. The browser makes an ajax request which initiates server-side self-polling. The ajax request remains open, waiting for a response until the file changes, and as soon as it gets a response, it makes a new long-polling request.

Here's what it looks like with jQuery and php, implementing the example of live-updating a div in the html showing the number of clients currently connected:

index.html:

<html>
<head>
<title>Comet Test</title>
  <script type="text/javascript" src="jquery.js"></script>
  <script type="text/javascript" src="longpolling.js"></script>
</head>
<body>
  Number of connected users: <div id="total">0</div>
</body>
</html>

longpolling.js:

$(document).ready(function() { connectToServer(1); });

function connectToServer( incp ) {
  $.get("LongPolling.php",
        { inc: incp },
        function(resp) {
          $('#total').html(resp);
          connectToServer(0);
        }
       );
}

LongPolling.php:

<?php

# (over)write file with contents, locking the file while doing so.
# just barf and die if there's an error.
function update($file, $contents)
{
  $f = fopen($file, 'w');
  if(!$f) { echo "ERROR1"; exit; } # couldn't open file for writing.
  if(!flock($f, LOCK_EX)) { echo "ERROR2"; exit; } # couldn't get lock.
  fwrite($f, $contents);
  fclose($f);  # this also releases the lock.
  return $contents;
}

# fetch the contents of the given file.
# if the file doesn't exist, create it with contents "0"
function fetch($file)
{
  if(file_exists($file)) {
    if(!is_readable($file)) { echo "ERROR3"; exit; }
    $x = file_get_contents($file);
  } else {
    $x = 0;
    update($file, $x);
  }
  return $x;
}

$fc = 'connx.txt';   # file that stores the number of connections.

if ( $_REQUEST['inc'] == 1 ) {  # someone just connected.
  echo update($fc, fetch($fc)+1);
} else {  # someone is reconnecting (also happens immediately after connect).
  $last = filemtime($fc);
  do {  # wait until some other instance causes $fc to change...
    sleep(1);
    clearstatcache(); # otherwise filemtime() results are cached!
  } while(filemtime($fc) == $last);
  echo fetch($fc);
}
?>

NOTE: This does not track disconnects, so it's more like live-tracking the total number of pageviews. See Running server-side function as browser closes for info on keeping track of browser disconnects, ie, server-side action on client disconnect.

Hawsepipe answered 4/1, 2010 at 21:25 Comment(1)
This seems to work fine for me on Firefox but on Safari and Chrome it shows the little spinny icon forever and never thinks it's finished loading the page. Any idea what's going on there? (Should I make this a separate StackOverflow question?)Gilbertogilbertson
H
1

Pushlets?

Habsburg answered 26/12, 2009 at 22:13 Comment(0)
B
0

Reverse AJAX is what you need. It's briefly explained in the DWR web page: http://directwebremoting.org/dwr/reverse-ajax/index.html - you can probably use one of the three flavours with the library you are using for ajax calls.

Bitterling answered 26/12, 2009 at 23:22 Comment(2)
Is that specific to the case of java on the server side?Gilbertogilbertson
DWR is java-specific, but I believe the techniques themselves can be implemented in any language, I do not see any reason why this could not be doneBitterling
S
0

As of Dec 2014, there is a W3C proposed recommendation called Server Sent Events (SSE) that would allow you to do that over HTTP: http://www.w3.org/TR/eventsource

It seems that it is a standardization of a group of techniques known as Comet. (which Darrel linked to in his answer)

A full example from 2013 with Sinatra can be found at: http://html5hacks.com/blog/2013/04/21/push-notifications-to-the-browser-with-server-sent-events/

There is also a 2010 HTML5 Rocks article: http://www.html5rocks.com/en/tutorials/eventsource/basics/ , but the spec is likely t have changed a bit since.

Most current browsers support this API, with the notable exception of IE11: http://caniuse.com/#feat=eventsource

Shallow answered 10/12, 2014 at 16:6 Comment(0)
F
-1

it is possible to write a java applet which can work as a network server. Once the applet has successfully started, it can report its port and ip number back to the remote server.

Then your server can send messages to the client server any time it feels like. Your java applet can then hand the message off to javascript, or do whatever else.

This method requires java plugin support however, which is far from universal.

Fortyfive answered 26/12, 2009 at 23:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.