一、WebSocket的前世今生:
Web应用的交互过程通常是客户端通过浏览器发出一个请求,服务器接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现,这种机制对于信息变化不是特别频繁的应用尚可,但对于实时要求高、海量并发的应用来说,高并发与用户实时响应是Web应用经常面临的问题,比如金融证券的实时信息、Web导航中的地理位置获取、社交网络的实时消息推送等。
传统的请求-响应模式的web开发在处理此类业务场景时,通常采用实时通讯方案,常见的是:
- 轮询:即客户端通过一定的时间间隔以频繁请求的方式向服务器发送请求,来保持客户端和服务器短的数据同步。问题很明显,当客户端以固定频率向服务器端发送请求时,服务器的数据可能没有更新,带来很多无所谓的请求,浪费带宽,效率低下。
- 基于Flash,AdobeFlash通过自己的Socket实现完成数据交换,再利用Flash暴露出相应的接口为JavaScript调用,从而达到实时传输的目的。此方式比轮询高效,且因为Flash安装率高,应用场景比较广泛,但在移动互联网终端上Flash的支持并不好。
二、WebSocket机制:
WebSocket是HTML5的一种新的协议。它实现了浏览器与服务器的全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在TCP之上,同HTTP一样通过TCP来传输数据,但它和HTTP最大的不同是:
- WebSocket是一种双向通信协议,在建立连接之后,WebSocket服务器能主动的向对方发送或接受数据,就像Socket一样
- WebSocket需要类似TCP的客户端和服务器端通过握手连接,连接成功后才能通信
webSocket模式客户端与服务器的交互
相对于传统HTTP每次请求都需要客户端与服务器端建立连接模式,WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket建立连接后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务器端发送和接收请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接收请求是在同一个持久连接上发起的,实时性优势明显。
下面,我们来看一个典型的WebSocket握手
<pre name="code" class="ruby"><pre name="code" class="html"><pre name="code" class="plain"><pre name="code" class="plain">GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websoket
Conntection:Upgrade
Sec-WebSocket-key:x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
熟悉HTTP的同学发现,这段类似HTTP协议的握手请求中,多了几个行:
Upgrade : websocket
Connection:Upgrade
这个就是WebSocket的核心了,告诉Apache、Nginx等服务器,我发起的是WebSocket请求
Sec-WebSocket-key:x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
首先,Sec-WebSocket-key是一个Base64 encode的值,这个是浏览器随机产生的,告诉服务器:不要忽悠我,我要验证是不是真的WebSocket助理。
然后,Sec-WebSocket-Protocol是一个用户定义的字符串,用来区分URL下,不同服务器所需要的协议。
最后,Sec-WebSocket-Version是告诉服务器所使用的WebSocket Draft(协议版本)。
然后服务器会返回下列东西,表示已经收到请求,成功建立WebSocket。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:HSmrc0sMIYUkAGmm50PpG2HaGWk=
Sec-WebSocket-Protocol: chat
这里开始就是HTTP最后负责的区域了,告诉客户,我已经成功切换协议了。
Upgrade:websocket
Connection:Upgrade
然后,Sec-WebSocket-Accept这个则是经过服务器确认,并且加密过后的Sec-WebSocket-Key。就向是给客户端证明自己的身份。
后面,Sec-WebSocket-Protocol则是表示最终使用的协议。