websocket使用与应用场景

websocket

websocket是服务器推送技术的一种,实现了浏览器与服务器的全双工通信。他的最大特点是服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送消息,实现双向平等对话。

建立连接过程

三次握手->建立http连接->客户端申请升级ws(upgrade:websocket)->返回101建立连接。

request header

1
2
3
4
5
6
7
8
9
10
11
12
13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: Upgrade
Cookie: SID=s%3AfLkx8qwQms1kMYBaLzCCNDOn6MA9OiDU.YiLibyv2QqazYf2%2BO1GLWfMXK5RjYXk9gO%2FL7vz%2Fu%2Bo
Host: localhost:8080
Origin: http://127.0.0.1:8080
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: 9l6hFemvcm1owsPWEbQqcQ==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36

response header

1
2
3
Connection: Upgrade
Sec-WebSocket-Accept: mV0aNTHxP90a2QZU+06dqSKLBcY=
Upgrade: websocket

为什么HTTP不允许服务端推送

如果允许Server向Client端主动推送数据,那么Client很容易受到攻击,特别是广告商会将广告信息,强行推送给Client,因此HTTP的单项特性是必要的。

websocket使用

在后端支持的情况下,建立websocket连接还是比较简单的:

1
const ws = new WebSocket('ws://localhost:8080');

常量

Ready state 常量:这些常量是readySate属性的取值,可以用来描述websocket连接的状态。

常量 描述
CONNECTING 0 连接还没开启
OPEN 1 连接已开启并准备好进行通信
CLOSING 2 连接正在关闭的过程中
CLOSED 3 连接已经关闭,或者连接无法建立

常用方法

属性名 类型 描述
onopen EventListener 一个用于连接打开的事件监听器,当readyState的值变为OPEN的时候触发该事件。该事件表明这个连接已经准备好接受和发送数据。
onmessage EventListener 一个用于消息事件的事件监听器,这一事件当有消息到达的时候该事件会触发。
onclose EventListener 用于监听连接关闭事件监听器。 当 WebSocket 对象的readyState 状态变为 CLOSED 时会触发该事件。
onerror EventListener 当错误发生时用于监听error事件的事件监听器。

websocket的特点

  • 建立在TCP协议之上,服务端和实现比较容易。
  • 与HTTP协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用HTTP协议。因此握手时不容易屏蔽,能通过各种HTTP代理服务器。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 节省带宽(HTTP协议的HEAD比较大)。
  • 节省服务器CPU资源(HTTP协议的Polling方式,即使Server没有数据也要接收Request)。

websocket的优势

  • 服务器与客户端之间交换的标头信息很小,大概只有2字节;
  • 客户端与服务器都可以主动传送数据给对方,真正的全双工;
  • 不用频率创建TCP请求及销毁请求,减少网络带宽资源的占用,同时也节省服务器资源;

websocket应用

  • 即时聊天室
  • 服务器消息推送
  • 前后端实时系统

上述应用传统解决方案

上述构建实时Web应用的场景,传统的解决方案是:轮询,长轮询、流。

轮询(polling)

轮询(polling)又称定期轮询:客户端定期向服务端发起请求,以此保持与Server端数据的同步。(通常使用Ajax,局部刷新Web页面)。

缺点:由于客户端顶起向服务端发送请求,当服务端没有数据更新时,客户端扔会发送请求,这就造成了带宽的浪费以及服务端cpu的耗费。

长轮询(long polling)

长轮询是对普通轮询的改进和提高,目标是降低无效的网络传输。基本原理:服务端收到客户端的请求之后,如果没有数据更新,则连接保持一段时间,直到有数据更新或者连接超时时,这样可以减少无效的客户端与服务端之间的交互,如:webQQ。

缺点:当服务端数据频繁更新时,服务端必须等待下一个请求到来,才能发送更新数据,这中间的延迟为2xRTT(往返时间),另外,在网络拥塞的情况下,等待时间更久;同时HTTP的数据包HEAD部分数据量很大(400+Byte),但真正有效的数据很少,这样的数据包在网络中周期传输,浪费带宽。

流(长连接)

流也称长连接方式,是指客户端在页面内使用一个隐蔽的窗口向服务端发起一个长连接请求。服务端接到这个请求后,进行响应,并且不断更新连接状态,保证连接不过期。这样可以保证服务端与客户端之间的实时通信。实例:Comet技术(基于HTTP长连接的服务端Push技术)。

缺点:大并发情况下,服务器可能会宕机。

websocket解决方案原理

WebSocket是为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信

一旦客户端和服务端都发送了握手信息并且成功握手,则数据传输部分将开始。数据传输对客户端和服务端而言都是一个双工通信通道,客户端和服务端来回传递的数据称之为“消息”。

Reference

MDN-websocket

WebSocket梳理