Websockets非常好用,经常被提到,但是Android设备和16%的浏览器不支持websockets(CanIUse.com)。许多服务器安装也不支持websockets,包括共享LAMP设置。如果您有一个共享主机或者想要广泛支持,websockets可能不是一个有效的选择。
长轮询是websockets的唯一有效替代方案。它具有更广泛的支持(它应该可以与几乎所有服务器和客户端一起使用),但是在不能很好地处理许多同时连接的服务器上(如Apache)有一个显著的缺点。另一个缺点是,无论有多少用户连接,您都必须执行许多常规数据库查询(可能每秒钟几个)。使用共享内存,例如PHP中的shm_attach()
,可以减轻这种负担。当服务器脚本监视到新消息时,它们会立即通过打开的连接发送。客户端将接收消息,然后使用新请求重新启动长连接。
如果您无法使用WebSockets,那么可以使用长轮询和短轮询混合的方式(见下文)。使用过长的轮询是不必要的且会占用过多资源。在持续连接大约10或15秒后,应该关闭它并切换到传统的短轮询,这只是一个常规的GET请求。
这个jQuery代码尚未经过测试,但您可以了解其中的思路:
function longpoll(lastid) {
console.log("Long polling started...");
if (typeof lastid == 'undefined') {
lastid = 0;
}
setTimeout(function () {
$.ajax({
url: "stream.php?long=1&lastid=" + lastid, success: function (payload) {
if (payload.status == "result") {
console.log("Long poll Msg: " + payload.lastid + ": " + payload.msg);
longpoll(lastid);
} else if (payload.status == "error") {
console.log("Long poll error.");
} else {
console.log("Long poll no results.");
}
shortpoll(lastid);
}, dataType: "json"
});
}, 15000);
};
function shortpoll(lastid) {
console.log("Short polling started.");
var delay = 500;
setInterval(function () {
console.log("setinterval started.");
$.ajax({
url: "stream.php?long=0&lastid=" + lastid, success: function (payload) {
if (payload.status == "result") {
console.log(payload.lastid + ": " + payload.msg);
longpoll(lastid);
} else if (payload.status == "error") {
console.log("Short poll error.");
} else {
console.log("Short poll. No result.");
}
}, dataType: "json"
});
delay = Math.min(delay + 10, 20000)
}, delay);
}
短轮询通过重复轮询(请求)来减少并发连接的数量。与往常一样,短轮询的缺点是获取新消息的延迟。然而,这类似于现实生活,所以不应该成为大问题。(如果有人在过去一周没有给你打电话,他们不太可能在接下来的五分钟内给你打电话,所以每五分钟检查手机是愚蠢的。)