Ajax、Comet、Websocket、SSE

 http 协议提及javascript

1996年IETF  HTTP工做组发布了HTTP协议的1.0版本 ,到如今广泛使用的版本1.1,HTTP协议经历了17 年的发展。这种分布式、无状态、基于TCP的请求/响应式、在互联网盛行的今天获得普遍应用的协议,相对于互联网的迅猛发展,它彷佛进步地很慢。互联网从兴起到如今,经历了门户网站盛行的web1.0时代,然后随着ajax技术的出现,发展为web应用盛行的web2.0时代,现在又朝着web3.0的方向迈进。反观http协议,从版本1.0发展到1.1,除了默认长链接以外就是缓存处理、带宽优化和安全性等方面的不痛不痒的改进。它一直保留着无状态、请求/响应模式,彷佛历来没意识到这应该有所改变。html

 

Ajax--- 脚本发送的 http 请求html5

传统的web应用要想与服务器交互,必须提交一个表单(form),服务器接收并处理传来的表单,而后返回全新的页面,由于先后两个页面的数据大部分都是相同的,这个过程传输了不少冗余的数据、浪费了带宽。因而Ajax技术便应运而生。java

Ajax是 Asynchronous JavaScript and XML 的简称,由Jesse James Garrett 首先提出。这种技术开创性地容许浏览器脚本(JS)发送http请求。Outlook Web Access小组于98年使用,并很快成为IE4.0的一部分,可是这个技术一直很小众,直到2005年初,google在他的goole groups、gmail等交互式应用中普遍使用此种技术,才使得Ajax迅速被你们所接受。web

Ajax的出现使客户端与服务器端传输数据少了不少,也快了不少,也知足了以丰富用户体验为特色的web2.0时代 初期发展的须要,可是慢慢地也暴露了他的弊端。好比没法知足即时通讯等富交互式应用的实时更新数据的要求。这种浏览器端的小技术毕竟仍是基于http协议,http协议要求的请求/响应的模式也是没法改变的,除非http协议自己有所改变。ajax

 

Comet--- 一种 hack 技术浏览器

以即时通讯为表明的web应用程序对数据的Low Latency要求,传统的基于轮询的方式已经没法知足,并且也会带来很差的用户体验。因而一种基于http长链接的“服务器推”技术便被hack出来。这种技术被命名为 Comet ,这个术语由Dojo Toolkit 的项目主管Alex Russell在博文 Comet: Low Latency Data for the Browser 首次提出,并沿用下来。缓存

其实,服务器推很早就存在了,在经典的client/server模型中有普遍使用,只是浏览器太懒了,并无对这种技术提供很好的支持。可是Ajax的出现使这种技术在浏览器上实现成为可能, google的gmail和gtalk的整合首先使用了这种技术。随着一些关键问题的解决(好比 IE 的加载显示问题),很快这种技术获得了承认,目前已经有不少成熟的开源Comet框架。安全

如下是典型的Ajax和Comet数据传输方式的对比,区别简单明了。典型的Ajax通讯方式也是http协议的经典使用方式,要想取得数据,必须首先发送请求。在Low Latency要求比较高的web应用中,只能增长服务器请求的频率。Comet则不一样,客户端与服务器端保持一个长链接,只有客户端须要的数据更新时,服务器才主动将数据推送给客户端。服务器

 

Comet的实现主要有两种方式:

  1. 基于Ajax的长轮询(long-polling)方式

浏览器发出XMLHttpRequest 请求,服务器端接收到请求后,会阻塞请求直到有数据或者超时才返回,浏览器JS在处理请求返回信息(超时或有效数据)后再次发出请求,从新创建链接。在此期间服务器端可能已经有新的数据到达,服务器会选择把数据保存,直到从新创建链接,浏览器会把全部数据一次性取回。

 

2.  基于 Iframe 及 htmlfile 的流(http streaming)方式

Iframe是html标记,这个标记的src属性会保持对指定服务器的长链接请求,服务器端则能够不停地返回数据,相对于第一种方式,这种方式跟传统的服务器推则更接近。

在第一种方式中,浏览器在收到数据后会直接调用JS回调函数,可是这种方式该如何响应数据呢?能够经过在返回数据中嵌入JS脚本的方式,如“<script type="text/javascript">js_func(“data from server ”)</script>”,服务器端将返回的数据做为回调函数的参数,浏览器在收到数据后就会执行这段JS脚本。

 

可是这种方式有一个明显的不足之处:IE、Morzilla Firefox 下端的进度栏都会显示加载没有完成,并且 IE 上方的图标会不停的转动,表示加载正在进行。Google 的天才们使用一个称为 “htmlfile” 的 ActiveX 解决了在 IE 中的加载显示问题,并将这种方法应用到了 gmail+gtalk 产品中。

Websocket--- 将来的解决方案

         若是说Ajax的出现是互联网发展的必然,那么Comet技术的出现则更多透露出一种无奈,仅仅做为一种hack技术,由于没有更好的解决方案。Comet解决的问题应该由谁来解决才是合理的呢?浏览器,html标准,仍是http标准?主角应该是谁呢?本质上讲,这涉及到数据传输方式,http协议应首当其冲,是时候改变一下这个懒惰的协议的请求/响应模式了。

W3C给出了答案,在新一代html标准html5中提供了一种浏览器和服务器间进行全双工通信的网络技术Websocket。从Websocket草案得知,Websocket是一个全新的、独立的协议,基于TCP协议,与http协议兼容、却不会融入http协议,仅仅做为html5的一部分。因而乎脚本又被赋予了另外一种能力:发起websocket请求。这种方式咱们应该很熟悉,由于Ajax就是这么作的,所不一样的是,Ajax发起的是http请求而已。 

与http协议不一样的请求/响应模式不一样,Websocket在创建链接以前有一个Handshake(Opening Handshake)过程,在关闭链接前也有一个Handshake(Closing Handshake)过程,创建链接以后,双方便可双向通讯。

Opening Handshake

    客户端发起链接Handshake请求

GET /chat HTTP/1.1

        Host: server.example.com

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

        Origin: http://example.com

        Sec-WebSocket-Protocol: chat, superchat

        Sec-WebSocket-Version: 13

         服务器端响应:

        HTTP/1.1 101 Switching Protocols

        Upgrade: websocket

        Connection: Upgrade

        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

        Sec-WebSocket-Protocol: chat

“Upgrade:WebSocket”表示这是一个特殊的 HTTP 请求,请求的目的就是要将客户端和服务器端的通信协议从 HTTP 协议升级到 WebSocket 协议。

“Sec-WebSocket-Key”是一段浏览器base64加密的密钥

“Sec-WebSocket-Accept”服务器端在接收到的Sec-WebSocket-Key密钥后追加一段神奇字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,并将结果进行sha-1哈希,而后再进行base64加密返回给客户端。

“Sec-WebSocket-Protocol”表示客户端请求提供的可供选择的子协议,及服务器端选中的支持的子协议,“Origin”服务器端用于区分未受权的websocket浏览器

“HTTP/1.1 101 Switching Protocols”中101为服务器返回的状态码,全部非101的状态码都表示handshake并未完成。

 

Data Framing

Websocket协议经过序列化的数据包传输数据。数据封包协议中定义了opcode、payload length、Payload data等字段。具体封包格式以下图所示:

 

FIN: 标识是否为此消息的最后一个数据包,占 1 bit

RSV1, RSV2, RSV3:  用于扩展协议,通常为0,各占1bit

Opcode:数据包类型(frame type),占4bits

         0x0:标识一个中间数据包

         0x1:标识一个text类型数据包

         0x2:标识一个binary类型数据包

         0x3-7:保留

         0x8:标识一个断开链接类型数据包

         0x9:标识一个ping类型数据包

         0xA:表示一个pong类型数据包

         0xB-F:保留

Payload length:Payload data的长度,占7bits,若是这个值等于126,则此后16bits用于表示Payload length,若是这个值等于127,则此后64bits用于表示Payload length

Payload data:应用层数据

Closing Handshake

相对于Opening Handshake,Closing Handshake则简单得多,主动关闭的一方向另外一方发送一个关闭类型的数据包,对方收到此数据包以后,再回复一个相同类型的数据包,关闭完成。

关闭类型数据包遵照封包协议,Opcode为0x8,Payload data能够用于携带关闭缘由或消息。 

虽然现阶段websocket协议还处于草案阶段,不过浏览器早就开始开始支持了,如下是不一样浏览器兼容列表:

 

Feature

Chrome

Firefox (Gecko)

Internet Explorer

Opera

Safari

Version -76 support Obsolete

6

4.0 (2.0)

Not supported

11.00 (disabled)

5.0.1

Protocol version 7 support Obsolete

Not supported

6.0 (6.0) 
Moz

Not supported

Not supported

Not supported

Protocol version 10 support Obsolete

14

7.0 (7.0) 
Moz

HTML5 Labs

?

?

Standard - RFC 6455 Support

16

11.0 (11.0)

10

12.10

6.0

从浏览器支持角度来看,websocket还有很长的路要走,特别是在中国这个IE6依然盛行的国家,即使在websocket标准化以后,旧版本浏览器的消亡也须要很长一段时间,所以现阶段comet依然是最好的解决方案。

SSE

传统的网页都是浏览器向服务器“查询”数据,可是不少场合,最有效的方式是服务器向浏览器“发送”数据。好比,每当收到新的电子邮件,服务器就向浏览器发送一个“通知”,这要比浏览器按时向服务器查询(polling)更有效率。

服务器发送事件(Server-Sent Events,简称SSE)就是为了解决这个问题,而提出的一种新API,部署在EventSource对象上。目前,除了IE,其余主流浏览器都支持。

简单说,所谓SSE,就是浏览器向服务器发送一个HTTP请求,而后服务器不断单向地向浏览器推送“信息”(message)。这种信息在格式上很简单,就是“信息”加上前缀“data: ”,而后以“\n\n”结尾。

SSE与WebSocket有类似功能,都是用来创建浏览器与服务器之间的通讯渠道。二者的区别在于:

WebSocket是全双工通道,能够双向通讯,功能更强;SSE是单向通道,只能服务器向浏览器端发送。

WebSocket是一个新的协议,须要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。

SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。

SSE默认支持断线重连,WebSocket则须要额外部署。

SSE支持自定义发送的数据类型。

从上面的比较能够看出,二者各有特色,适合不一样的场合。

目前开发的项目中有两处用到了SSE:

1.锁屏,用户登陆成功后,启动一个SSE进程,服务器自定义一个事件,每隔几秒返回用户的状态,浏览器监听这个事件,当用户的登陆状态失效果,弹出登陆框让他登陆,以此达到锁屏的效果。

2.新消息提醒。服务器定义消息提醒事件,浏览器监听这个事件,当有新消息时,以Web Notification的方式弹出消息,并可定义用户的点击事件。

相关文章
相关标签/搜索