WebSocket实战

前言html

  互联网发展到如今,早已超越了原始的初衷,人类历来没有像如今这样依赖过他;也正是这种依赖,促进了互联网技术的飞速发展。而终端设备的创新与发展,更加速了互联网的进化;前端

HTTP/1.1规范发布于1999年,同年12月24日,HTML4.01规范发布;尽管已到2012年,但HTML4.01还是主流;虽然 HTML5的草案已出现了好几个年头,但转正日期,遥遥无期,少则三五年,多则数十年;而HTML5的客户代理(对于通常用户而言,就是浏览器),则已百 家争鸣,星星向荣;再加上移动终端的飞速发展,在大多数状况下,咱们均可以保证拥有一个HTML5的运行环境,因此,咱们来分享一下HTML5中的 WebSocket协议;android

本文包含如下六个方面:web

1. WebSocket的前世此生sql

2. WebSocket是什么chrome

3. 为何使用WebSocketnpm

4. 搭建WebSocket服务器编程

5. WebSocket APIjson

6. 实例解析浏览器

以上六点分为两大块,前3点侧重理论,主要让你们明白WebSocket是什么,然后3点则结合代码实战,加深对WebSocket的认知。

1、WebSocket的前世此生

  Web 应用的信息交互过程一般是客户端经过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,而后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,可是对于那些实时要求比较高的应用来讲就显得捉襟见肘了。咱们须要一种高效节能的双向通讯机制来保证数据的实时传输。有web TCP之称的WebSocket应运而生,给开发人员提供了一把强有力的武器来解决疑难杂症。

2、WebSocket是什么?

  其实,从背景介绍中,咱们大体的能够猜出,WebSocket是干什么用的。前面咱们提到,WebSocket有web TCP之称,既然是TCP,确定是用来作通讯的,可是它又有不一样的地方,WebSocket做为HTML5中新增的一种通讯协议,由通讯协议和编程API组成,它可以在浏览器和服务器之间创建双向链接,以基于事件的方式,赋予浏览器原生的实时通讯能力,来扩展咱们的web应用,增长用户体验,提高应用的性 能。何谓双向?服务器端和客户端能够同时发送并响应请求,而再也不像HTTP的请求和响应。

3、为何使用WebSocket

  在WebSocket出现以前,咱们有一些其它的实时通信方案,比较经常使用的有轮询,长轮询,流,还有基于Flash的交换数据的方式,接下来,咱们一一分析一下,各类通讯方式的特色。

①轮询

  这是最先的一种实现实时web应用的方案;原理比较简单易懂,就是客户端以必定的时间间隔向服务器发送请求,以频繁请求的方式来保持客户端和服务器端的数据同步。可是问题也很明显:当客户端以固定频率向服务器端发送请求时,服务器端的数据可能并无更新,这样会带来不少无谓的请求,浪费带宽,效率低下。

②长轮询

  长轮询是对定时轮询的改进和提升,目地是为了下降无效的网络传输。当服务器端没有数据更新的时候,链接会保持一段时间周期直到数据或状态改变或者时间过时,经过这种机制来减小无效的客户端和服务器间的交互。固然,若是服务端的数据变动很是频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提升。

③流

  长轮询是对定时轮询的改进和提升,目地是为了下降无效的网络传输。当服务器端没有数据更新的时候,链接会保持一段时间周期直到数据或状态改变或者时间过时,经过这种机制来减小无效的客户端和服务器间的交互。固然,若是服务端的数据变动很是频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提升。

④基于Flash的实时通信方式

  Flash有本身的socket实现,这为实时通讯提供了可能。咱们能够利用Flash完成数据交换,再利用Flash暴露出相应的接口,方便 JavaScript调用,来达到实时传输数据的目的。这种方式比前面三种方式都要高效,并且应用场景比较普遍;由于flash自己的安装率很高;可是在当前的互联网环境下,移动终端对flash的支持并很差,以IOS为主的系统中根本没有flash的存在,而在android阵营中,虽然有flash的支持,但实际的使用效果差强人意,即便是配置较高的移动设备,也很难让人满意。就在前几天(2012年6月底),Adobe官方宣布,不在支持 android4.1之后的系统,这基本上宣告了flash在移动终端上的死亡。

下面是轮询和长轮询的信息流转图:

  对比完四种不一样的实时通讯方式,不难发现,除了基于flash的方案外,其它三种方式都是用AJAX方式来模拟实时的效果,每次客户端和服务器端交互时,都是一次完整的HTTP请求和应答的过程,而每一次的HTTP请求和应答都带有完整的HTTP头信息,这就增长每次的数据传输量,并且这些方案中客 户端和服务端的编程实现比较复杂。接下来,咱们再来看一下WebSocket,为何要使用它呢?高效节能,简单易用。

下图是来自websocket.org的测试结果:

  在流量和负载增大的状况下,WebSocket方案相比传统的Ajax轮询方案有极大的性能优点;而在开发方面,也十分简单,咱们只须要实例化WebSocket,建立链接,查看是否链接成功,而后就能够发送和相应消息了。 咱们会在后面的实例中去详细的说明API。

4、搭建WebSocket服务器

  其实,在服务器的选择上很广,基本上,主流语言都有WebSocket的服务器端实现,而咱们做为前端开发工程师,固然要选择如今比较火热的NodeJS做为咱们的服务器端环境了。NodeJS自己并无原生的WebSocket支持,可是有第三方的实现(你们要是有兴趣的话,彻底能够参考WebSocket协议来作本身的实现),咱们选择了“ws”做为咱们的服务器端实现。因为本文的重点是讲解WebSocket,因此,对于NodeJS不作过多的介绍,不太熟悉的朋友能够去参考NodeJS入门指南。安装好NodeJS以后,咱们须要安装“ws”,也就是咱们的WebSocket实现,安装方法很简单,在终端或者命令行中输入:npm install ws,等待安装完成就能够了。接下来,咱们须要启动咱们的WebSocket服务。首先,咱们须要构建本身的HTTP服务器,在NodeJS中构建一个简单的HTTP服务器很简单,so easy。代码以下:var app = http.createServer(onRequest ).listen( 8888 );onRequest()做为回调函数,它的做用是处理请求,而后作出响应,实际上就是根据接收的URL,在服务器上查找相应的资源,最终返回给浏览器。在构建了HTTP服务器后,咱们须要启动WebSocket服务,代码以下:

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer( { server : app } );

  从代码中能够看出,在初始化WebSocket服务时,把咱们刚才构建好的HTTP实例传递进去就好。到这里,咱们的服务端代码差很少也就编写完成了。怎么样?很简单吧。

5、WebSocket API

上面咱们介绍了WebSocket服务端的知识,接下来,咱们须要编写客户端代码了。在前面咱们说过,客户端的API也是一如既往的简单:

  见上图:ready state中定义的是socket的状态,分为connection、open、closing和closed四种状态,从字面上就能够区分出它们所表明的状态。

上图描述的是WebSocket的事件,分为onopen、onerror和onclose;

  上图为消息的定义,主要是接收和发送消息。注意:能够发送二进制的数据。因为WebSocket API(截止到2012年7月)仍是草案,API文档和上文所描述的会有所不一样,请以官方文档为主,这也是我为何不详细描述API中各个属性的缘由。另一点须要提醒你们的是:在前端开发中,浏览器兼容是必不可少的,而WebSocket在主浏览器中的兼容仍是不错的,火狐和Chrome不用说,最新版的支持很是不错,并且支持二进制数据的发送和接收。可是IE9并不支持,对于国内的大多数应用场景,WebSocket没法大规模使用。

  之因此选择百度的统计数据,是由于更加符合国内的实际状况。图中所展现的是2012年4月1日到2012年6月30日之间的统计数据,从图中不难看出IE6.0、奇虎360、IE7.0和IE8.0加起来一共 占据了77%的市场,FireFox属于其余,chrome只有5.72%的份额,再一次告诉咱们,咱们的主战场依然是IE系。既然是IE系,那么对于WebSocket在实际app中的应用就基本不可能了。但咱们彻底能够在chrome、FireFox、以及移动版的IOS浏览器中使用它。

6、实例解析

  搭建好了服务端,熟悉了API,接下来,咱们要开始构建咱们的应用了。鉴于WebSocket自身的特色,咱们的第一个demo选择了比较常见的聊天程序,咱们暂且取名为chat。说到聊天,你们最早想到的确定是QQ,没错,咱们所实现的应用和QQ相似,并且仍是基于web的。由于是demo,咱们的功能比较简陋,仅实现了最简单的会话功能。就是启动WebSocket服务器后,客户端发起链接,链接成功后,任意客户端发送消息,都会被服务器广播给全部已链接的客户端,包括本身。

  既然须要客户端,咱们须要构建一个简单的html页面,页面中样式和元素,你们能够自由发挥,只要可以输入消息,有发送按钮,最后有一个展现消息的区域便可。具体的样子你们能够看附件中的demo。写玩HTML页面以后,咱们须要添加客户端脚本,也就是和WebSocket相关的代码;前面咱们说过,WebSocket的API自己很简单,因此,咱们的客户端代码也很直接,以下:

var wsServer = 'ws://localhost:8888/';
var websocket = new WebSocket(wsServer);
websocket.binaryType = "arraybuffer";
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;

  首先,咱们须要指定WebSocket的服务地址,也就是var wsServer = 'ws://localhost:8888/';而后,咱们实例化WebSocket,new WebSocket(wsServer),剩下的就是指定相应的回调函数了,分别是onOpen,onClose,onMessage和onError,对于我们的实验应用来讲,onopen、onclose、onerror甚至能够无论,我们重点关注一下onmessage。onmessage()这个回调函数会在客户端收到消息时触发,也就是说,只要服务器端发送了消息,咱们就能够经过onmessage拿到发送的数据,既然拿到了数据,接下去该怎么玩,就随便咱们了。请看下面的伪代码:

function onMessage(evt) {
 var json = JSON.parse(evt.data);
 commands[json.event](json.data);
}

  由于onmessage只接收字符串和二进制类型的数据,若是须要发送json格式的数据,就须要转换一下格式,把字符串转换成JSON格式。只要是支持WebSocket,确定原生支持window.JSON,因此,咱们能够直接使用JSON.parse()和 JSON.stringify()来进行转换。转换完成后,咱们就获得了咱们想要的数据了,接下来所作的工做就是将消息显示出来。实际上就是

Elements.innerHTML += data + '</br>';

  上面展示了客户端的代码,服务器端的代码相对要简单一些,由于咱们的服务器端使用的是第三方实现,咱们只须要作一些初始化工做,而后在接收到消息时,将消息广播出去便可,下面是具体的代码:

var app = http.createServer( onRequest ).listen( 8888 );
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer( { server : app } );
wss.on('connection', function( ws ) {
    console.log('connection successful!');
    ws.on('message', function( data, flags ){
    console.log(data);
    //do something here
    });
    ws.on('close', function() {
      console.log('stopping client');
   });
});

  咱们能够经过wss.clients得到当前已链接的全部客户端,而后遍历,获得实例,调用send()方法发送数据;

var clients = wss.clients, len = clients.length, i = 0;
  for( ; i <len; i = i + 1 ){
  clients[i].send( msg );
 }

  说到这里,一个双向通讯的实例基本完成。

  最后,咱们须要明确一点,WebSocket自己的优势很明显,可是做为一个正在演变中的web规范,咱们必须清楚的认识到WebSocket在构 建应用时的一些风险;虽然自己有不少局限性,可是这项技术自己确定是大势所趋,WebSocket在移动终端,在chrome web store都有用武之地,咱们能够进行大胆的尝试,让咱们在技术的革新中不被淘汰。

相关文章
相关标签/搜索