假设有一个动态生成内容的网页——比如一个包含当前连接浏览器数量的 div。当服务器上的计数发生变化时,我希望所有连接的浏览器重新加载计数,以便每个人都能看到增量/减量。
实现这一目标的最佳方法是什么?
关键词:ajax、广播、浏览器、div、jquery
假设有一个动态生成内容的网页——比如一个包含当前连接浏览器数量的 div。当服务器上的计数发生变化时,我希望所有连接的浏览器重新加载计数,以便每个人都能看到增量/减量。
实现这一目标的最佳方法是什么?
关键词:ajax、广播、浏览器、div、jquery
我认为COMET可能是您正在寻找的。 Web Sockets将是理想的,但缺乏浏览器采用不会使其现在变得实用。
HTTP 协议在设计上是无状态的。实现这一点的唯一方法是通过 AJAX 实现客户端轮询。
这是使用 ajax 长轮询执行服务器推送的方法。浏览器发出 ajax 请求,启动服务器端自轮询。ajax 请求保持打开状态,等待响应,直到文件更改,一旦得到响应,它就会发出新的长轮询请求。
这是jQuery和 php的样子,实现了在 html 中实时更新 div 的示例,显示当前连接的客户端数量:
索引.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);
}
);
}
长轮询.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);
}
?>
注意:这不会跟踪断开连接,因此它更像是实时跟踪总浏览量。有关跟踪浏览器断开连接的信息,请参阅在浏览器关闭时运行服务器端功能,即客户端断开连接时的服务器端操作。
小推车?
反向 AJAX 是您所需要的。在 DWR 网页中对其进行了简要说明:http: //directwebremoting.org/dwr/reverse-ajax/index.html - 您可以将这三种风格中的一种与用于 ajax 调用的库一起使用。
截至 2014 年 12 月,W3C 提出了一项名为服务器发送事件 (SSE) 的建议,允许您通过 HTTP 执行此操作:http: //www.w3.org/TR/eventsource
它似乎是一组被称为 Comet的技术的标准化。(达雷尔在他的回答中链接到)
2013 年使用 Sinatra 的完整示例可在以下位置找到: http: //html5hacks.com/blog/2013/04/21/push-notifications-to-the-browser-with-server-sent-events/
还有一篇 2010 年 HTML5 Rocks 文章:http ://www.html5rocks.com/en/tutorials/eventsource/basics/ ,但从那以后规范可能没有改变。
当前大多数浏览器都支持此 API,但 IE11 除外:http ://caniuse.com/#feat=eventsource
可以编写一个可以用作网络服务器的 Java 小程序。一旦小程序成功启动,它可以将其端口和 ip 号报告回远程服务器。
然后,您的服务器可以随时向客户端服务器发送消息。然后,您的 java 小程序可以将消息传递给 javascript,或执行其他任何操作。
但是,此方法需要 java 插件支持,这远非通用。