zoukankan      html  css  js  c++  java
  • 【HTML5】HTML5 WebSocket简介以及简单示例

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

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

    本文包含以下六个方面:
    1. WebSocket的前世今生
    2. WebSocket是什么
    3. 为什么使用WebSocket
    4. WebSocket API

    5. DEMO

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

    一、WebSocket的前世今生

    Web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种 机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说就显得捉襟见肘了。我们需要一种高效节能的双向通信机制来保证数 据的实时传输。有web TCP之称的WebSocket应运而生,给开发人员提供了一把强有力的武器来解决疑难杂症。
    (PS:其实,在早期的HTML5规范中,并没有包含WebSocket的定义,一些早期的HTML5书籍中,完全没有WebSocket的介绍。直到后来,才加入到当前的草案中。)

    二、WebSocket是什么?

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

    三、为什么使用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。

    四、WebSocket API

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

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


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


    上图为消息的定义,主要是接收和发送消息。注意:可以发送二进制的数据。

    以上个图的具体的含义就不再一一赘述,详细描述请参考:
    http://www.w3.org/TR/2012/WD-websockets-20120524/
    PS:由于WebSocket API(截止到2012年7月)还是草案,API文档和上文所描述的会有所不同,请以官方文档为主,这也是我为什么不详细描述API中各个属性的原因。

    另外一点需要提醒大家的是:在前端开发中,浏览器兼容是必不可少的,而WebSocket在主浏览器中的兼容还是不错的,火狐和Chrome不用 说,最新版的支持非常不错,而且支持二进制数据的发送和接收。但是IE9并不支持,对于国内的大多数应用场景,WebSocket无法大规模使用。

    截图来自(http://tongji.baidu.com/data/browser),之所以选择百度的统计数据,是因为更加符合国内的实际情况。图中 所展示的是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浏览器中使用它。

    五、DEMO

    NodeJS比较简单,所以选择NodeJS,本身并没有原生的WebSocket支持,但是有第三方的实现(大家要是有兴趣的话,完全可以参考WebSocket协议来做自己的实现),我们选择了“ws”作为我们的服务器端实现。

    安装ws:npm install ws

    关于ws,具体查看http://einaros.github.io/ws/  简介

    DEMO有ws.html,ws.js 

    ws.html源码:

     1 <html>
     2 <head>
     3 <title>这是一个测试用例</title>
     4 </head>
     5 <body>
     6 
     7 <p id="info"></p>
     8 <p><input type="text" id="name"/></p>
     9 <p><input type="text" id="msg"/></p>
    10 <p><input type="button" id="sub"/></p>
    11 
    12 <script type="text/javascript">
    13 function $(str){
    14     return document.getElementById(str);
    15 }
    16 var name = $('name');
    17 var msg = $('msg');
    18 var info = $('info');
    19 var sub = $('sub');
    20 var ws = new WebSocket('ws://localhost:8080/');
    21 ws.onopen = function(){
    22     info.innerHTML = '连接成功建立<br/>';
    23 }
    24 ws.onmessage = function(e){
    25     info.innerHTML += e.data+'<br/>';
    26 }
    27 sub.onclick = function(){
    28     ws.send(name.value+":"+msg.value);
    29 }
    30 </script>
    31 </body>
    32 </html>

    ws.js源码:

     1 var cons = new Array();
     2 var ws = require('ws').Server;
     3 var server = new ws({host:"localhost",port:8080});
     4 server.on('connection',function(ws){
     5   console.log('new connection founded successfully');
     6   cons.push(ws);
     7   ws.on('message',function(data){
     8     for(var i=0;i<cons.length;i++){
     9         cons[i].send(data);
    10     }
    11   });
    12   ws.on('close',function(){
    13     for(var i=0;i<cons.length;i++){
    14        if(cons[i] == ws) cons.splice(i,1);
    15     }
    16   });
    17 });
    18 console.log('websocket-server running...');

    麻痹,本来博客园编辑器有上传压缩包的,现在木有了,次奥

    参考:http://ued.sina.com.cn/?p=900

  • 相关阅读:
    使用C++为对象分配与释放内存时的几个好习惯
    OGRE渲染流程
    【问题解决记录】无法识别的标志“-sdlMode”,在“p2”中
    四元数 Quaternion
    《The Cg Tutorial》阅读笔记——凹凸贴图 Bump Mapping
    尝试优化骨骼动画计算的意外收获——使用嵌入式汇编对float转int进行优化
    Model 的 Meta 选项
    dns资料
    ansible中的变量
    DockerFile与docker-compose.yml是什么
  • 原文地址:https://www.cnblogs.com/sniper007/p/3357629.html
Copyright © 2011-2022 走看看