Websockets 很棒,并且经常被提及,但是 Android 设备和 16% 的浏览器不支持 websockets ( CanIUse.com )。许多服务器安装也不支持 websocket,包括共享 LAMP 设置。如果你有一个共享主机或者如果你想获得广泛的支持,websockets 可能不是一个有效的选择。
长轮询是 websocket 的唯一有效替代方案。它有更广泛的支持(它应该适用于几乎所有的服务器和客户端),但它在不能很好地处理许多同时连接的服务器上(比如 Apache)有一个明显的缺点。另一个缺点是,无论连接了多少用户,您都必须执行许多常规数据库查询(可能每秒几次)。使用共享内存,就像shm_attach()
在 PHP 中一样,可以减轻这个负担。当服务器脚本监视新消息时,一旦发现它们就会立即通过打开的连接发送。客户端将收到消息,然后使用新请求重新启动长连接。
如果您不能使用 websockets,很可能就是这种情况,您可以使用长短轮询混合(见下文)。使用非常长的轮询是不必要的,并且会占用太多资源。在持续连接大约 10 或 15 秒后,您应该将其关闭并切换到老式的短轮询,这只是重复的常规 GET 请求。
此 jQuery 代码未经测试,但您明白了:
function longpoll(lastid) {
/* Start recursive long polling. The server script must stay
connected for the 15 seconds that the client waits for a response.
This can be done with a `while()` loop in PHP. */
console.log("Long polling started...");
if (typeof lastid == 'undefined') {
lastid = 0;
}
//long polling...
setTimeout(function () {
$.ajax({
url: "stream.php?long=1&lastid=" + lastid, success: function (payload) {
if (payload.status == "result") {
//result isn't an error. lastid is used as bookmark.
console.log("Long poll Msg: " + payload.lastid + ": " + payload.msg);
longpoll(lastid); //Call the next poll recursively
} else if (payload.status == "error") {
console.log("Long poll error.");
} else {
console.log("Long poll no results.");
}
/* Now, we haven't had a message in 15 seconds. Rather than
reconnect by calling poll() again, just start short polling
by repeatedly doing an normal AJAX GET request */
shortpoll(lastid); //start short polling after 15 seconds
}, dataType: "json"
});
}, 15000); //keep connection open for 15 seconds
};
function shortpoll(lastid) {
console.log("Short polling started.");
//short polling...
var delay = 500; //start with half-second intervals
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); //Call the next poll recursively
} 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) //increment but don't go over 20 seconds
}, delay);
}
短轮询减少了并发连接的数量,而是使用重复轮询(请求)。与往常一样,短轮询的缺点是延迟获取新消息。但是,这类似于现实生活,所以应该没什么大不了的。(如果有人在过去一周内没有给你打电话,他们不太可能在接下来的五分钟内给你打电话,所以每五分钟检查一次你的手机是很愚蠢的。)