WebSocket通信
在 服务器推送技术 中,我们介绍了一些常见的方法,来获取服务器的推送消息,但是数据流仍然是由客户端所发送的请求驱动的,另外无论是AJAX轮询的方式,或者是流消息的形式,或多或小都采取了一些取巧的方式。这里我们在介绍一种更加有效的解决方案,就是WebSocke的通信,WebSocket提供了"在一个单个的TCP连接上提供双向的通信,结合WebSocket API方法,它为网页和远程服务器之间的双向通信提供了一种替代HTTP轮询的方案。"
WebSocket 在客户端和服务器之间提供了真正的双向数据交换。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
WebSocket是个规范,在实际的实现中有HTML5规范中的WebSocket API和WebSocket的子协议STOMP。Web浏览器和服务器都必须实现 WebSockets 协议来建立和维护连接。WebSocket的特点如下:
- HTML5 中的协议,实现与客户端与服务器双向,基于消息的文本或二进制数据通信
- 适合于对数据的实时性要求比较强的场景,如通信、直播、共享桌面,特别适合于客户与服务频繁交互的情况下,如实时共享、多人协作等平台
- 采用新的协议,后端需要单独实现
- 客户端并不是所有浏览器都支持
WebSocket通信握手
WebSocket通信其实是借助了Http协议来完成一部分的握手,过程如下:
在客户端发起请求时,其中 Connection 必须设置 Upgrade,表示客户端希望连接升级。Upgrade 字段必须设置 Websocket,表示希望升级到 Websocket 协议。Sec-WebSocket-Key
是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算 SHA-1 摘要,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操作,可以尽量避免普通 HTTP 请求被误认为 Websocket 协议。
Sec-WebSocket-Version
表示支持的 Websocket 版本。RFC6455 要求使用的版本是 13,之前草案的版本均应当弃用。
在服务端,Upgrade: websocket, 及Connection: Upgrade 依然是固定的,告诉客户端即将升级的是 Websocket 协议,而不是 mozillasocket,lurnarsocket 或者 shitsocket。Sec-WebSocket-Accept
这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key 。Sec-WebSocket-Protocol
则是表示最终使用的协议。
至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行。
至于WebSocket的子协议STOMP 和 WebSocke API 的使用,这个会在后面的实例中进行介绍,这里我们就来比较一下WebSocket通信和我们之前在 服务器推送技术 中介绍的技术进行对比,如下:
AJAX短轮询 | Servlet异步 | SSE | WebSocket | |
---|---|---|---|---|
浏览器支持度 | 最高 | 高 | 中 | 低 |
实时性 | 最低 | 较高 | 高 | 最高 |
代码实现复杂度 | 最容易 | 较容易 | 容易 | 最复杂 |
在实际运用中,不一定哪一种技术最好,这里需要在具体的业务场景下进行分析,比如我们在购物平台上进行购物,在进行支付时,等待支付成功时,就会自动的跳转,那么这里会使用什么技术呢?为了客户体验,会使用实时性最高的WebSocket 的么?一般来说是不会的,最可能的时使用短轮询,因为一旦用户过多,使用WebSocket之类的是需要非常多的服务器来维持用户连接的,而且也不是所有进行浏览的用户都一定会进行支付的。