Loading

Web通信中传统轮询、长轮询和WebSocket简介

引用地址:https://zhuanlan.zhihu.com/p/25690011

http请求 轮询

为了定时获取并刷新页面上的数据,客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。

结合Ajax客户端实现如下:

setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);

上面的程序会每隔10秒向服务器请求一次数据,并在数据到达后存储。这个实现方法通常可以满足简单的需求,然而同时也存在着很大的缺陷:在网络情况不稳定的情况下,服务器从接收请求、发送请求到客户端接收请求的总时间有可能超过10秒,而请求是以10秒间隔发送的,这样会导致接收的数据到达先后顺序与发送顺序不一致。于是出现了采用setTimeout的轮询方式:

function poll() {
    setTimeout(function() {
        $.get("/path/to/server", function(data, status) {
            console.log(data);
            // 发起下一次请求
            poll();
        });
    }, 10000);
}

程序首先设置10s后发起请求,当数据返回后,调用请求函数再隔10s发起第二次请求,以此类推。这样的话虽然无法保证两次请求之间的时间间隔为固定值,但是可以保证到达数据的顺序。

  • 优点:后端程序编写比较容易(几乎不用做什么特殊处理)。
  • 缺点:因为是不断请求,服务端有没有更新数据都会返回。这就造成了请求中有大半是无用,浪费带宽和服务器资源。
  • 实例:适用于小型应用。

长轮询:发过去,等一会,再回来

上面所说的传统轮询方式都存在一个严重缺陷:程序每发出一次请求就要新建一个Http请求。因为发起Http请求时会有很多头部信息,真正的请求信息几乎很少,这样就会造成资源浪费,频繁的轮询使得Web服务器遭受"凌迟"之苦。

而长轮询意味着浏览器只需启动一个HTTP请求,其连接的服务器会“hold”住此次连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的Http请求,以此类推。

实现原理:

img

轮询可能在以下3种情况时终止。

  • 有新数据推送 。当服务器向浏览器推送信息后,应该主动结束程序运行从而让连接断开,这样浏览器才能及时收到数据。
  • 没有新数据推送 。应该设定一个最长时限,避免WEB服务器超时(Timeout),若一直没有新信息,服务器应主动向浏览器发送本次轮询无新信息的正常响应,并断开连接,这也被称为“心跳”信息。
  • 网络故障或异常 。由于网络故障等因素造成的请求超时或出错也可能导致轮询的意外中断,此时浏览器将收到错误信息。
  • 优点:在无消息的情况下不会频繁的请求,耗费资源小。
  • 缺点:服务器hold住连接会消耗资源,返回数据顺序无保证,难于管理维护。
  • 实例:WebQQ、Hi网页版、Facebook IM。

WebSocket(以tornado为例)

服务端主动向客户端推送的情况,使用websocket

WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通讯协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。 在WebSocket API中,浏览器服务器只需要做一个握手的动作,然后,浏览器服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息。

posted @ 2022-06-26 14:58  香菜根  阅读(162)  评论(0编辑  收藏  举报