服务端推送
http协议通信只能由客户端发起。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用”轮询”:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
1. websocket
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
概括起来就是:双向的,可跨域,可传输文本二进制。
连接过程:
1) 客户端发送http的get请求:
- Upgrade: websocket
- Connection: Upgrade
- 必须包含Sec-WebSocket-Key头部,值是一个Base64编码的16字节随机字符串。
- 必须包含Sec-WebSocket-Version头部,值必须为13
2) 服务端验证客户端的握手包符合规范之后也会发送一个握手包给客户端。格式如下: - 状态行中返回Switching Protocol
- 必须包含Connection头部,值必须为Upgrade
- 必须包含一个Upgrade头部,值必须为websocket
- 必须包含一个Sec-Websocket-Accept头部,值是根据如下规则计算的:首先将一个固定的字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接到Sec-WebSocket-Key对应值的后面。对拼接后的字符串进行一次SHA-1计算将计算结果进行Base-64编码
客户端收到服务端的握手包之后,验证报文格式时候符合规范,以2)中同样的方式计算Sec-WebSocket-Accept并与服务端握手包里的值进行比对。
2. server-sent event
SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。总体来说,WebSocket 更强大和灵活。因为它是全双工通道,可以双向通信;SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。如果浏览器向服务器发送信息,就变成了另一次 HTTP 请求。
其他特点包括:
(1) SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
(2) SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。
(3) SSE 默认支持断线重连,WebSocket 需要自己实现。
(4) SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
(5) SSE 支持自定义发送的消息类型。
概括起来特点就是:单向的,基于文本的,客户端自动重连的。
适用场景:实时监控、股票报价
3. Commet(长轮询和流)
传统轮询是浏览器定时向服务器发送请求,看有没有更新的数据。
长轮询是客户端发送请求,等待服务端响应。服务端拿到请求,一直保持连接打开,直到有数据或是超时的时候返回。发送完数据,浏览器关闭连接,随即又发起一个到服务器的心情求。这一过程在页面打开期间一直持续不断。
轮询的优势:所有浏览器都支持,因为使用XHR和setTimeout就能实现。
流不同于上面两种轮询,因为它在页面的整个生命周期内只使用一个HTTP连接,具体来说就是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性的向浏览器发送数据。