WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它的出现使客户端和服务器之间的数据交换变得更加简单。WebSocket 通常被应用在实时性要求较高的场景,例如赛事数据、股票证券、网页聊天和在线绘图等。
WebSocekt 与 HTTP 协议完全不同,但同样被广泛应用。无论是后端开发者、前端开发者、爬虫工程师或者信息安全工作者,都应该掌握 WebSocekt 协议的知识。
在本篇文章中,你将收获如下知识:
读懂 WebSocket 协议规范文档 RFC6455
WebSocket 与 HTTP 的关系
数据帧格式及字段含义
客户端与服务端交互流程
客户端与服务端如何保持连接
何时断开连接
本篇文章适用于互联网领域的开发者和产品经理
开始WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 通信协议于 2011 年被 IETF 定为标准 RFC6455,并由 RFC7936 补充规范。看到这里,很多读者会有疑问:什么是 RFC?
RFC 是一系列以编号排定的文件,它由一系列草案和标准组成。几乎所有互联网通信协议均记录在 RFC 中,例如 HTTP 协议标准、本篇介绍的 WebSocket 协议标准、Base64 编码规范等。除此之外,RFC 还加入了许多论题。在本篇 Chat 中,我们对 WebSocekt 的学习和讨论将基于 RFC6455。
WebSocket 协议的来源
在 WebSocket 协议出现以前,网站通常使用轮询来实现类似“数据实时更新”这样的效果。要注意的是,这里的“数据实时更新”是带有引号的,这表示并不是真正意义上的数据实时更新。轮询指的是在特定的时间间隔内,由客户端主动向服务端发起 HTTP 请求,以确认是否有新数据的行为。下图描述了轮询的过程:
首先,客户端会向服务端发出一个 HTTP 请求,这个请求的意图就是向服务器询问“大哥,有新数据吗?”。服务器在接收到请求后,根据实际情况(有数据或无数据)做出响应:
有数据,我发给你;
无数据,你待会再问;
这种一问一答的方式有着明显的缺点,即浏览器需要不断的向服务器发出请求。由于 HTTP 请求包含较长的头部信息(例如 User-Agent、Referer 和 Host 等),其中真正有效的数据可能只是很小的一部分,所以这样会浪费很多的带宽资源。
比轮询更好的“数据实时更新”手段是 Comet。这种技术可以实现双向通信,但依然需要反复发出请求。而且在 Comet 中,采用的是 HTTP 长连接,这同样会消耗服务器资源。在这种情况下,HTML5 定义了更节省资源,且能够让双端稳定实时通信的 WebSocket 协议。在 WebSocket 协议下,客户端和服务端只需要完成一次握手,就直接可以创建持久性的连接,并进行双向数据传输。下图描述了 WebSocket 协议中,双端通信的过程:
WebSocket 的优点
相对于 HTTP 协议来说,WebSocket 具有开销少、实时性高、支持二进制消息传输、支持扩展和更好的压缩等优点。这些优点如下所述:
较少的开销
WebSocket 只需要一次握手,在每次传输数据时只传输数据帧即可。而 HTTP 协议下,每次请求都需要携带完整的请求头信息,例如 User-Agent、Referer 和 Host 等。所以 WebSocket 的开销相对于 HTTP 来说会少很多。
更强的实时性
由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于一问一答的 HTTP 来说,WebSocket 协议下的数据传输的延迟明显更少。
支持二进制消息传输
WebSocket 定义了二进制帧,可以更轻松地处理二进制内容。
支持扩展
开发者可以扩展协议,或者实现部分自定义的子协议。
更好的压缩
Websocket 在适当的扩展支持下,可以沿用之前内容的上下文。这样在传递类似结构的数据时,可以显著地提高压缩率。
WebSocket 协议规范
WebSocket 是一个通信协议,该协议的规范与标准均记录在 RFC6455 中。协议共有 14 个部分,但与协议规范相关的只有 11 个部分:
介绍
术语和其他约定
WebSocket URI
握手规范
数据帧
发送和接收数据
关闭连接
错误处理
扩展
通信安全
注意事项
而与本篇 Chat 相关的为 4、5、6、7 部分的内容,这些也是 WebSocket 中较为重要的内容。接下来,我们就来学习这些知识。
双端交互流程
客户端与服务端连接成功之前,使用的通信协议是 HTTP。连接成功后,使用的才是 WebSocket 协议。下图描述了双端交互的流程: