WebSocket

什么是 WebSocket

WebSocket 是一个网络传输协议,可以在一个 TCP 连接上进行全双工通信,在 TCP/IP 四层概念模型和 OSI 七层网络模型中都属于应用层。

为什么要创造 WebSocket

一般情况下,我们进行网络通信使用的是 HTTP 协议,但是 HTTP 协议有一个致命的缺点就是:通信只能由客户端主动发起,而服务器不能主动向客户端发消息。

对于数据的实时性要求较高的场景,如股票的实时交易行情数据、聊天室等,要想获取服务器的最新数据,可以通过轮询或者 Comet 的方式,但这两种方式的效率很低,浪费资源。

Comet 本质上也是轮询,只是当服务器收到请求时,如果当前没有新消息,会先将线程挂起,当有新消息时再恢复,这种方式虽然能解决实施性的问题,但是极大的浪费服务器资源。此外,一个 HTTP 连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能会将这个连接关闭,而网关对于我门来说是不可控的,因此 Comet 需要定期发一些 ping 数据保持连接的存活状态。

为了弥补 HTTP 协议的缺点,WebSocket 应运而生。

WebSocket 的特点

WebSocket 最大的特点就是除了客户端可以向服务器发送信息外,服务器可以主动向客户端推送消息,是真正的双向平等关系,可以用于服务器推送技术中。

WebSocket 建立在 TCP 协议之上,服务端实现成本低;与 HTTP 协议兼容性高,默认端口也是 80 或 443(WebSockets, wss),握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

WebSocket 创建连接的过程

首先,WebSocket 连接必须由客户端主动发起,请求协议是一个标准的 HTTP 请求,报文格式如下:

GET ws://121.40.165.18:8800 HTTP/1.1
Host: 121.40.165.18:8800
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: xxxxxxxxxxx(客户端生成的随机字符串)
Sec-WebSocket-Version: 13

WebSocket 的请求报文和普通 HTTP 请求报文有些不同:

  • GET 请求的地址不是 path,而是以 ws:// 开头的地址
  • 多了两个 Connection: Upgrade 和 Upgrade: websocket 请求头,表示该请求要被转换为 WebSocket 连接
  • Sec-WebSocket-Key:用于标识连接的唯一性,不是用于加密的密钥
  • Sec-WebSocket-Version:指定来 WebSocket 的协议版本

服务器收到请求后,就会返回如下报文:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:xxxxxxxxxx(服务端端生成的随机字符串)

该响应代码 101 表示本次连接的 HTTP 协议即将被更改,更改后的协议就是 Upgrade: 指定的 WebSocket 协议。

现在,一个 WebSocket 连接就建立成功,客户端和服务器就可以随时主动发送消息给对方。消息有两种,一种是文本,一种是二进制数据。

为什么 WebSocket 连接可以实现全双工通信而 HTTP 连接不行呢?实际上 HTTP 协议是建立在 TCP 协议之上的,TCP 协议本身就实现了全双工通信,但是 HTTP 协议的请求-应答机制限制了全双工通信。WebSocket 连接建立以后,其实只是简单规定了一下:接下来,咱们通信就不使用 HTTP 协议了,直接互相发数据吧。

安全的 WebSocket 连接机制和 HTTPS 类似。首先,客户端用wss://xxx 创建 WebSocke t连接时,会先通过 HTTPS 创建安全的连接,然后,该 HTTPS 连接升级为 WebSocket 连接,底层通信走的仍然是安全的 SSL/TLS 协议。

WebSocket 与 Socket 的关系

首先 WebSocket 是应用层的协议,而 Socket 是传输层协议的具体实现,二者不能相提并论,如果一定要说有什么联系的话,那就是 WebSocket 的数据传输是依赖 Socket 来传输的。

参考

  • https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096
  • https://www.ruanyifeng.com/blog/2017/05/websocket.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注