一、一切为了通信
为了避免概念混淆,这里阐明一下,本文所说的端与端特指B/S(Browser/Server)架构下客户端(即浏览器)与服务端。
随着Web应用的兴起,B/S架构(即浏览器/服务器架构)应运而生。B/S架构中采取了 浏览器请求、服务器响应 的工作模式,这就造成了端与端之间数据通信的单一——即服务端无法主动传输数据给浏览器端。当遇到需要获取实时数据的场景,比如请假审批,此时常见的方式是浏览器向服务器端不断发起轮询来查询对应的数据。
浏览器发起的轮询一般有两种,分为 短轮询 和 长轮询 ,两者都基于HTTP协议实现,属于非持久连接。
短轮询
:一般采用 Ajax 实现。即浏览器端每隔固定时间向服务器端发起HTTP请求,尝试获取最新的数据。长轮询
:长轮询整体逻辑上和短轮询相似,也是浏览器端向服务器端发起HTTP请求尝试获取最新的数据。但是和短轮询不同的是,长轮询在请求未获取到数据时会在服务器端阻塞,直至获取到最新数据或者等待超时。
上面所说的两种轮询方式,或多或少都会有相应的缺陷。短轮询即时发送实时返回,不会阻塞,但是为了保证实时数据的获取,在某些场景下轮询的频率会非常高。长轮询阻塞式获取方式虽然避免了高频率的访问请求,但是每次请求服务端都需要将请求阻塞,消耗较多的资源去维持对应的长轮询。以上两种请求在极端情况都会对服务器端造成极大的负担。
那么是否有什么方式能够多快好省的完成浏览器端和服务器端之间的实时通信呢?基于这样的需求,WebSocket协议由此诞生。
二、“平等”的通信
WebSocket 是一种建立在单个TCP连接上进行全双工通信的协议。这就意味着,使用WebSocket进行通信的双方地位是 “平等的” ,数据的推送既可以从浏览器端发起,也可以从服务器端发起。
我们再回头来看下上面的问题,上面的问题本质上是因为B/S架构中使用的HTTP协议是标准的 请求—响应 工作模式,在这一模式中只能由浏览器发起数据查询请求,服务端不能主动推送数据。这就造成了数据传输的非实时性,即使使用轮询的方式,也只能达到准实时。
使用WebSocket协议则能很好地解决上面服务端无法主动发起数据推送的问题。相对于HTTP请求需要等待浏览器端发起请求才能响应,实时性更强。即使是和Comet等类似的长轮询相比,WebSocket在并发性和数据处理上也显得更加优越。下面我们就来看下WebSocket建立连接和通信的过程吧。
三、WebSocket通信过程
WebSocket协议和HTTP协议都是建立在TCP协议之上的,但是HTTP协议受限于其特殊的工作模式,只能作为一个半双工的通信协议使用,而WebSocket协议则较为完善的继承了TCP协议相应特性。WebSocket协议和HTTP协议并无太大关系,但是为了保证兼容现有的浏览器握手规范,WebSocket使用HTTP来进行协议进行握手用以建立连接。
使用WebSocket协议进行通信分为两个阶段,分别是握手阶段和通信阶段。
握手阶段
:在握手阶段,由浏览器端使用HTTP协议向服务器端发起建立连接请求,这一阶段和TCP协议的握手逻辑相似,只有握手成功之后才能建立通信连接。在这一过程中,WebSocket依赖HTTP协议发起握手请求,但和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 "Upgrade: WebSocket" 表明这是一个申请协议升级的 HTTP 请求,这就意味着握手成功后会进行通信协议的切换,将HTTP协议切换成WebSocket协议;通信阶段
:在成功建立连接之后,此时在浏览器端和服务端会建立持久性的连接,通信的双方都能够主动向另一方推送数据或接受数据,即支持数据的双向传输。在这一过程,数据都是以 帧序列的形式 进行传输,数据帧既可以是文本,也可以是二进制流。
除了通信方式上发生的变化,在数据传输方面,WebSocket也做出了相应的优化。对于HTTP协议来说,由于其无状态的特性,导致每次发送请求都需要包含完整的协议头。WebSocket则不同,它是一个有状态协议,在完成握手成功建立连接之后,浏览器端和服务器端的连接将保持活动状态,直至通信的任何一方关闭连接。在连接维持阶段,由于相应的状态信息或身份验证信息在握手阶段已经获取,浏览器端和服务器端之间只需要传输实际数据,其余协议报文则被大大减少,这就意味着传输过程中的开销大大减少。
四、总结
WebSocket有如此多的优点,是否就意味着可以将HTTP协议取而代之了?回答当然是不可以。在文章之初我们已经指明了,WebSocket协议最佳的使用场景是进行实时数据交换,比如在线聊天室等场景。在目前的大部分Web应用使用场景中,更多的还是由浏览器端(即用户侧)触发资源获取或变更的请求,然后服务器再进行响应,即请求—响应的工作模式。更不要说,WebSocket的握手是基于HTTP协议来完成的,所以HTTP协议的主体地位依然不可动摇。
关于介绍WebSocket API相关的文档教程不胜其多,这里就不展开进行介绍,有兴趣的同学可以自行百度了解一下。