一 websocket javascript
WebSocket是html5新增长的一种通讯协议,目前流行的浏览器都支持这个协议,例如 Chrome,Safrie,Firefox,Opera,IE等等,对该协议支持最先的应该是chrome,从chrome12就已经开始支持,随着协 议草案的不断变化,各个浏览器对协议的实现也在不停的更新。该协议仍是草案,没有成为标准,不过成为标准应该只是时间问题了。html
1. WebSocket APIhtml5
首先看一段简单的javascript代码,该代码调用了WebSockets的API。java
var ws = new WebSocket(“ws://echo.websocket.org”);node
ws.onopen = function(){ws.send(“Test!”); };git
ws.onmessage = function(evt){console.log(evt.data);ws.close();};程序员
ws.onclose = function(evt){console.log(“WebSocketClosed!”);};github
ws.onerror = function(evt){console.log(“WebSocketError!”);};web
这份代码总共只有5行,如今简单概述一下这5行代码的意义。ajax
第一行代码是在申请一个WebSocket对象,参数是须要链接的服务器端的地址,同http协议使用http://开头同样,WebSocket协议的URL使用ws://开头,另外安全的WebSocket协议使用wss://开头。
第二行到第五行为WebSocket对象注册消息的处理函数,WebSocket对象一共支持四个消息 onopen, onmessage, onclose和onerror,当Browser和WebSocketServer链接成功后,会触发onopen消息;若是链接失败,发送、接收数据 失败或者处理数据出现错误,browser会触发onerror消息;当Browser接收到WebSocketServer发送过来的数据时,就会触发 onmessage消息,参数evt中包含server传输过来的数据;当Browser接收到WebSocketServer端发送的关闭链接请求时, 就会触发onclose消息。咱们能够看出全部的操做都是采用消息的方式触发的,这样就不会阻塞UI,使得UI有更快的响应时间,获得更好的用户体验。
2 为何引入WebSocket协议?
Browser已经支持http协议,为何还要开发一种新的WebSocket协议呢?咱们知道http协议是一种单向的网络协议,在创建链接后,它只 容许Browser/UA(UserAgent)向WebServer发出请求资源后,WebServer才能返回相应的数据。而WebServer不能 主动的推送数据给Browser/UA,当初这么设计http协议也是有缘由的,假设WebServer能主动的推送数据给Browser/UA,那 Browser/UA就太容易受到攻击,一些广告商也会主动的把一些广告信息在不经意间强行的传输给客户端,这不能不说是一个灾难。那么单向的http协 议给如今的网站或Web应用程序开发带来了哪些问题呢?
让咱们来看一个案例,如今假设咱们想开发一个基于Web的应用程序去获取当前Web服务器的实时数据,例如股票的实时行情,火车票的剩余票数等等,这就需 要Browser/UA与WebServer端之间反复的进行http通讯,Browser不断的发送Get请求,去获取当前的实时数据。下面介绍几种常 见的方式:
1. Polling
这种方式就是经过Browser/UA定时的向Web服务器发送http的Get请求,服务器收到请求后,就把最新的数据发回给客户端(Browser /UA),Browser/UA获得数据后,就将其显示出来,而后再按期的重复这一过程。虽然这样能够知足需求,可是也仍然存在一些问题,例如在某段时间 内Web服务器端没有更新的数据,可是Browser/UA仍然须要定时的发送Get请求过来询问,那么Web服务器就把之前的老数据再传送过 来,Browser/UA把这些没有变化的数据再显示出来,这样显然既浪费了网络带宽,又浪费了CPU的利用率。若是说把Browser发送Get请求的 周期调大一些,就能够缓解这一问题,可是若是在Web服务器端的数据更新很快时,这样又不能保证Web应用程序获取数据的实时性。
2. Long Polling
上面介绍了Polling遇到的问题,如今介绍一下LongPolling,它是对Polling的一种改进。
Browser/UA发送Get请求到Web服务器,这时Web服务器能够作两件事情,第一,若是服务器端有新的数据须要传送,就当即把数据发回给 Browser/UA,Browser/UA收到数据后,当即再发送Get请求给Web Server;第二,若是服务器端没有新的数据须要发送,这里与Polling方法不一样的是,服务器不是当即发送回应给Browser/UA,而是把这个 请求保持住,等待有新的数据到来时,再来响应这个请求;固然了,若是服务器的数据长期没有更新,一段时间后,这个Get请求就会超 时,Browser/UA收到超时消息后,再当即发送一个新的Get请求给服务器。而后依次循环这个过程。
这种方式虽然在某种程度上减少了网络带宽和CPU利用率等问题,可是仍然存在缺陷,例如假设服务器端的数据更新速率较快,服务器在传送一个数据包给 Browser后必须等待Browser的下一个Get请求到来,才能传递第二个更新的数据包给Browser,那么这样的话,Browser显示实时数 据最快的时间为2×RTT(往返时间),另外在网络拥塞的状况下,这个应该是不能让用户接受的。另外,因为http数据包的头部数据量每每很大(一般有 400多个字节),可是真正被服务器须要的数据却不多(有时只有10个字节左右),这样的数据包在网络上周期性的传输,不免对网络带宽是一种浪费。
经过上面的分析可知,要是在Browser能有一种新的网络协议,能支持客户端和服务器端的双向通讯,并且协议的头部又不那么庞大就行了。WebSocket就是肩负这样一个使命登上舞台的。
3 websocket协议
WebSocket协议是一种双向通讯协议,它创建在TCP之上,同http同样经过TCP来传输数据,可是它和http最大的不一样有两 点:1.WebSocket是一种双向通讯协议,在创建链接后,WebSocket服务器和Browser/UA都能主动的向对方发送或接收数据,就像 Socket同样,不一样的是WebSocket是一种创建在Web基础上的一种简单模拟Socket的协议;2.WebSocket须要经过握手链接,类 似于TCP它也须要客户端和服务器端进行握手链接,链接成功后才能相互通讯。
下面是一个简单的创建握手的时序图:
这里简单说明一下WebSocket握手的过程。
当Web应用程序调用new WebSocket(url)接口时,Browser就开始了与地址为url的WebServer创建握手链接的过程。
1. Browser与WebSocket服务器经过TCP三次握手创建链接,若是这个创建链接失败,那么后面的过程就不会执行,Web应用程序将收到错误消息通知。
2. 在TCP创建链接成功后,Browser/UA经过http协议传送WebSocket支持的版本号,协议的字版本号,原始地址,主机地址等等一些列字段给服务器端。
例如:
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
3. WebSocket服务器收到Browser/UA发送来的握手请求后,若是数据包数据和格式正确,客户端和服务器端的协议版本号匹配等等,就接受本次握手链接,并给出相应的数据回复,一样回复的数据包也是采用http协议传输。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
4. Browser收到服务器回复的数据包后,若是数据包内容、格式都没有问题的话,就表 示本次链接成功,触发onopen消息,此时Web开发者就能够在此时经过send接口想服务器发送数据。不然,握手链接失败,Web应用程序会收到 onerror消息,而且能知道链接失败的缘由。
4 websocket与TCP,HTTP的关系
WebSocket与http协议同样都是基于TCP的,因此他们都是可靠的协议,Web开发者调用的WebSocket的send函数在browser 的实现中最终都是经过TCP的系统接口进行传输的。WebSocket和Http协议同样都属于应用层的协议,那么他们之间有没有什么关系呢?答案是确定 的,WebSocket在创建握手链接时,数据是经过http协议传输的,正如咱们上一节所看到的“GET/chat HTTP/1.1”,这里面用到的只是http协议一些简单的字段。可是在创建链接以后,真正的数据传输阶段是不须要http协议参与的。
具体关系能够参考下图:
5 websocket server
若是要搭建一个Web服务器,咱们会有不少选择,市场上也有不少成熟的产品供咱们应用,好比开源的Apache,安装后只需简单的配置(或者默认配置)就可 以工做了。可是若是想搭建一个WebSocket服务器就没有那么轻松了,由于WebSocket是一种新的通讯协议,目前仍是草案,没有成为标准,市场 上也没有成熟的WebSocket服务器或者Library实现WebSocket协议,咱们就必须本身动手写代码去解析和组装WebSocket的数据 包。要这样完成一个WebSocket服务器,估计全部的人都想放弃,幸亏的是市场上有几款比较好的开源库供咱们使用,好比 PyWebSocket,WebSocket-Node, LibWebSockets等等,这些库文件已经实现了WebSocket数据包的封装和解析,咱们能够调用这些接口,这在很大程度上减小了咱们的工做 量。如
下面就简单介绍一下这些开源的库文件。
1. PyWebSocket
PyWebSocket采用Python语言编写,能够很好的跨平台,扩展起来也比较简单,目前WebKit采用它搭建WebSocket服务器来作LayoutTest。
咱们能够获取源码经过下面的命令
svn checkouthttp://pywebsocket.googlecode.com/svn/trunk/ pywebsocket-read-only
更多的详细信息能够从http://code.google.com/p/pywebsocket/获取。
2. WebSocket-Node
WebSocket-Node采用JavaScript语言编写,这个库是创建在nodejs之上的,对于熟悉JavaScript的朋友可参考一下,另外Html5和Web应用程序受欢迎的程度愈来愈高,nodejs也正受到普遍的关注。
咱们能够从下面的链接中获取源码
https://github.com/Worlize/Websocket-Node
3. LibWebSockets
LibWebSockets采用C/C++语言编写,可定制化的力度更大,从TCP监听开始到封包的完成咱们均可以参与编程。
咱们能够从下面的命令获取源代码
git clone git://git.warmcat.com/libwebsockets
值得一提的是:websocket是能够和http共用监听端口的,也就是它能够公用端口完成socket任务。
二 Socket.io
node.js提供了高效的服务端运行环境,可是因为浏览器端对HTML5的支持不一,为了兼容全部浏览器,提供卓越的实时的用户体验,而且为程序员提供客户端与服务端一致的编程体验,因而socket.io诞生。Socket.io将Websocket和轮询 (Polling)机制以及其它的实时通讯方式封装成了通用的接口,而且在服务端实现了这些实时机制的相应代码。也就是说,Websocket仅仅是 Socket.io实现实时通讯的一个子集。那么,Socket.io都实现了Polling中的那些通讯机制呢?
Adobe® Flash® Socket 大部分PC浏览器都支持的socket模式,不过是经过第三方嵌入到浏览器,不在W3C规范内,因此可能将逐步被淘汰,何况,大部分的手机浏览器都不支持这种模式。
AJAX long polling 这个很好理解,全部浏览器都支持这种方式,就是定时的向服务器发送请求,缺点是会给服务器带来压力而且出现信息更新不及时的现象。
AJAX multipart streaming 这是在XMLHttpRequest对象上使用某些浏览器(好比说Firefox)支持的multi-part标志。Ajax请求被发送给服务器端并保 持打开状态(挂起状态),每次须要向客户端发送信息,就寻找一个挂起的的http请求响应给客户端,而且全部的响应都会经过统一链接来写入
var xhr = $.ajaxSettings.xhr(); xhr.multipart =true; xhr.open('GET', 'ajax', true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { processEvents($.parseJSON(xhr.responseText)); } }; xhr.send(null);
Forever Iframe (永存的Iframe)技术涉及了一个置于页面中的隐藏Iframe标签,该标签的src属性指向返回服务器端事件的servlet路径。 每次在事件到达时,servlet写入并刷新一个新的script标签,该标签内部带有JavaScript代码,iframe的内容被附加上这一 script标签,标签中的内容就会获得执行。这种方式的缺点是接和数据都是由浏览器经过HTML标签来处理的,所以你没有办法知道链接什么时候在哪一端已被 断开了,而且Iframe标签在浏览器中将被逐步取消使用。
JSONP Polling JSONP轮询基本上与HTTP轮询同样,不一样之处则是JSONP能够发出跨域请求,详细请搜索查询jsonp的内容。