WebSocket初识

1,658 阅读7分钟

一、WebSocket 介绍

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。

WebSocket,是一种网络传输协议,位于OSI模型的应用层。可在单个TCP连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通迅

websocket是一种网络通信协议,我们都知道http协议,http协议只能从客户端主动发起,不能从服务端推送数据到客户端。而WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。它必须依赖 HTTP 协议在浏览器和服务器端完成一次握手,握手成功后,两者之间就直接可以创建持久性的连接,并进行双向数据传输(数据直接从 TCP 通道传输,与 HTTP 无关)。即:websocket分为握手和数据传输阶段,即进行了HTTP握手 + 双工的TCP连接。

很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。(定时器+Ajax),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

image.png 它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性,默认端口也是80和443。并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 全双工(通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合,例如指 A→B 的同时 B→A ,是瞬时同步的)
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
ws://www.chrono.com
ws://www.chrono.com:8080/srv
wss://www.chrono.com:445/im?user_id=xxx

二、WebSocket API

浏览器发送给服务器

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
  • Upgrade: websocket 和 Connection: Upgrade,告诉 nginx、apache 等服务器,此次请求是 websocket 请求。
  • Sec-WebSocket-Key 是一个 Base64 encode 的值,这个是浏览器随机生成的,告诉服务器:泥煤,不要忽悠窝,我要验证尼是不是真的是Websocket助理。
  • Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分相同 URL 下,不同的服务所需要的协议。简单理解:今晚我要服务A,别搞错啦~
  • Sec-WebSocket-Version 是告诉服务器所使用的 Websocket Draft (协议版本)

服务器返回:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
  • 同样,Upgrade: websocket 和 Connection: Upgrade,告诉浏览器成功切换协议为 websocket.

  • Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key。 服务器:好啦好啦,知道啦,给你看我的ID CARD来证明行了吧。

  • Sec-WebSocket-Protocol 则是表示最终使用的协议. (至此,http作用已经完成)

  • WebSocket 构造函数

    WebSocket 对象作为一个构造函数,用于新建 WebSocket 实例。

    var Socket = new WebSocket('wss://echo.websocket.org');
    

    执行上面语句之后,客户端就会与服务器进行连接。

  • webSocket.readyState

      CONNECTING:值为0,表示正在连接。
    
      OPEN:值为1,表示连接成功,可以通信了。
    
      CLOSING:值为2,表示连接正在关闭。
    
      CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
    

    下面是一个示例。

    switch (Socket.readyState) {
    case WebSocket.CONNECTING:
      console.log('正在连接!')
      break;
    case WebSocket.OPEN:
      console.log('连接成功!')
      break;
    case WebSocket.CLOSING:
      console.log('连接正在关闭!')
      break;
    case WebSocket.CLOSED:
      console.log('连接已经关闭!')
      break;
    default:
      // this never happens
      break;
      }
    
  • WebSocket 事件

    事件事件处理程序描述
    openSocket.onopen连接建立时触发
    messageSocket.onmessage客户端接收服务端数据时触发
    errorSocket.onerror通信发生错误时触发
    closeSocket.onclose连接关闭时触发

    实例对象的 onopen 属性,用于指定连接成功后的回调函数。

    Socket.onopen = function () {
    	console.log('Hello Word!');
      };
    

    如果要指定多个回调函数,可以使用 addEventListener 方法。

    Socket.addEventListener('open', function (event) {
    	console.log('Hello Word!');
      });
    
  • WebSocket 方法

    方法描述
    Socket.send()使用连接发送数据
    Socket.close()关闭连接

    发送文本的例子。

    Socket.send('your message');
    

    发送 Blob 对象的例子。

    var file = document.querySelector('input[type="file"]').files[0];
      Socket.send(file);
    

三、传统方式

传统轮询(Traditional Polling)

当前Web应用中较常见的一种持续通信方式,通常采取 setInterval 或者 setTimeout 实现。例如如果我们想要定时获取并刷新页面上的数据,可以结合Ajax写出如下实现:

setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);

上面的程序会每隔10秒向服务器请求一次数据,并在数据到达后存储。这个实现方法通常可以满足简单的需求,然而同时也存在着很大的缺陷:在网络情况不稳定的情况下,服务器从接收请求、发送请求到客户端接收请求的总时间有可能超过10秒,而请求是以10秒间隔发送的,这样会导致接收的数据到达先后顺序与发送顺序不一致。于是出现了采用 setTimeout 的轮询方式:

function poll() {
    setTimeout(function() {
        $.get("/path/to/server", function(data, status) {
            console.log(data);
            // 发起下一次请求
            poll();
        });
    }, 10000);
}

程序首先设置10秒后发起请求,当数据返回后再隔10秒发起第二次请求,以此类推。这样的话虽然无法保证两次请求之间的时间间隔为固定值,但是可以保证到达数据的顺序。

缺陷

程序在每次请求时都会新建一个HTTP请求,然而并不是每次都能返回所需的新数据。当同时发起的请求达到一定数目时,会对服务器造成较大负担。

长轮询(long poll)

客户端发送一个request后,服务器拿到这个连接,如果有消息,才返回response给客户端。没有消息,就一直不返回response。之后客户端再次发送request, 重复上次的动作。

总结

http协议的特点是服务器不能主动联系客户端,只能由客户端发起。它的被动性预示了在完成双向通信时需要不停的连接或连接一直打开,这就需要服务器快速的处理速度或高并发的能力,是非常消耗资源的。

四、优点

  • 较少的控制开销:数据包头部协议较小,不同于http每次请求需要携带完整的头部
  • 更强的实时性:相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少
  • 保持创连接状态:创建通信后,可省略状态信息,不同于HTTP每次请求需要携带身份验证
  • 更好的二进制支持:定义了二进制帧,更好处理二进制内容
  • 支持扩展:用户可以扩展websocket协议、实现部分自定义的子协议
  • 更好的压缩效果:Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率

五、WebSocket 应用

  • 即时聊天--多人聊天
  • 天气
  • 后台统计数据更新
  • 消息推送(抢购、秒杀提醒)
  • 商城后台商品编辑是锁定
  • 协调编辑文档

六、总结

  1. websocket是一个类似http的一种通讯协议。
  2. websocket最大的特点是客户端和服务端能相互给对方发送消息。
  3. websocket广泛引用在需要实时通讯的一些应用上面。
  4. websocket没有同源限制,而且性能开销小,通信高效。 参考文章

juejin.cn/post/686349…

github.com/febobo/web-…