日期:2014-05-16  浏览次数:20626 次

Ajax push技术核心揭秘(转)
Ajax push技术核心揭秘

引言
         在web应用普及的今天,用户开始将更多的关键应用向Web迁移, 广大Web应用开发者与推广者在享受到了成功地喜悦。与同时很多用户已经开始抱怨我们的Web应用总是那么被动与迟钝,何时才能让他们的应用更加主动实时的,让发生在服务端的事件第一时间内通知给他们。然而开发人员也不得不面对这样的事实,在Web天生的无状态与非连接制约下无法他们无法对应用的实时性更进一步的提升。
在近几年的发展特别是Aajx的出现让我们的web应用找到了新的兴奋点,然而这仍然没有解决前面提到的问题,难道我们真的无路可走了?
经过笔者的探索发现我们是可以实现基于web的实时主动通知的, 即采用Ajax push技术,她可以让我们web应用拥有前所未有激动人心的功能和使用体验。笔者将通过本文带领逐步大家去实现这个激动人心的体验。笔者目的也非常简单,目的在于为大家提供更多的参考资料 ,无论对错希望本文能起到抛砖引玉的作用.如果能借此引发大家对Web实时推式通知技术的更为广泛的讨论我将感到万分荣幸!

Ajax push的广阔前景
         通知技术笔者把它们从概念上分为两种:被动的拉式通知技术和主动的推式通知技术。这两种说法目前网上已经有大量的文章,我在这里只做简单的介绍:
1、 被动的拉式通知技术又称Pull方式如下图
       

浏览器
服务器
internet
定时请求
根据请求响应
图:pull方式
拉方式需要客户机不定时的检查服务器已获知是否发生新的事件或数据是否有变化,这种方式并不实时,但在web上比较容易实现。
2、 主动的推式通知技术又称push方式如下图

浏览器
服务器
internet
发生事件主动发送
首次建立通信连接
事件
图:push方式
推式客户机与服务只需建立好连接之后,每当服务器有特殊事件发生时才通知客户机,该方式实时性非常强,但目前在Web上实现较为复杂
       
这两种方式后者有非常显著的优点,而Ajax push就是需要在web上实现的后者的通信技术,如果Ajax push能被的完美实现,那么基于web的IM软件、基于Web的关键业务报警系统、基于web的实时监控系统、更智能人性的Web信息系统、甚至是基于web的远程控制系统、等等都将可以实现,同时彻底摆脱客户端部署与安装,避免服务端的高负载。而webMsn、GMAIL这些系统中的很多被我们认为是不可思议的特性也能被任何一个web程序员轻松的开发出来。这是多么美好的时刻,更加值得我们去期待。

突破观念的束缚
Web应用的优点在于易于部署,但web是无状态非连接的,从这个角度来看服务器无法对客户端进行实时的推式通知,可能会有人对我说的不屑于顾,不是已经有很多系统都实现了web上的通知吗?其实不然,目前实现web上动态通知的技术概括下来基本上有以下两种方法:
1、              定期刷新法。定期刷新法又可以分为整体页面间隔刷新和异步间隔刷新两种方法。
a)         整体页面间隔刷新法,该方法在早期聊天室中使用,该方法实现非常简单,只需要在Html头中加入如下代码:
<META HTTP-EQUIV="refresh" CONTENT="10" URL="你的页面">
该方法目前已经很少使用,主要因为如果现在网页过于复杂加载时间长,如果频繁刷新会对用户造成非常差的体验,同时会传输大量重复的网络数据无疑加大了服务器及网络的负担。
b)         异步间隔刷新法,由于采用异步刷新方法,即使刷新平凡都不会造成页面闪烁,同时减少了不必要的展现数据,是目前采用的较多的方法,实现上又分为Ajax刷新即XMLHttp刷新和隐藏贞刷新。我给出简单现示例如下:
Ajax刷新
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.5.0");
function refreshUi()
{
         xmlhttp.open("POST","你接收请求的页面",true);
  xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
         xmlhttp.send(你好提交的数据);
  var s=xmlhttp.responseText;//获取服务器收到的数据
         UpdateUi(s);//更新你的界面上的数据
}
setInterval(refreshUi,20);
服务段可以是一个可以是jsp,asp,serverlet,aspx,等服务端处理程序,然后通过Response对象向客户端输出需要的数据即可
隐藏贞刷新
即在页面上放入隐藏的FrameSet或则IFrame,然后通过对该贞的提交操作获取数据然后刷新页面
function refreshUi()
{
        var hiddenForm= document.frames[1].document.forms[0];//获取隐藏贞中的表单信息
hiddenForm.submit();//对表单进行提交
        updateUi(hiddenForm);//对界面进行更新

}
setInterval(refreshUi,20);
但采用定期刷新法后不管是Ajax提交还是隐藏贞提交都有共同的缺点是跟新不实时,刷新速度不能过快否则将严重影响客户端或服务器的性能,同时很多客户的数据在相当长的时间内一般不会更新,这样的会造成无大量无意义的刷新,同时增大服务器的负载。但由于该方法实现简单,所以大量的web应用程序采用了该方法实现通知技术,属于非实时拉动(被动)式通知技术。
2、              客户端插件法,通过为客户段编写第三方插件的形式嵌入到客户端网页中,然后同服务器建立通信连接实现即时通知技术,该技术有点可以实现服务端到客户端的主动推式通知技术,目前主要是以ActiveX或是java Applet的方式提供插件。缺点是实现技术复杂,需要让客户安装插件,容易出现不兼容的情况,同时在目前网络病毒泛滥的情况下,很多客户端浏览器上的安全策略是禁止安装第三方的插件,这对部署和维护都带来了相当大的难度。
从上面的技术实现上看目前这两种方法目前缺点都非常明显要么非实时性,同时服务器负担巨大;要么安装插件,没有发挥web的优点。所以我们必须跳出常规方法寻找另外的方法,幸运的是经过笔者研究和尝试基本上找到实现服务器实时主动通知客户端的实现思路。
揭开神秘的面纱
         事先说明,笔者在当前文章中只会提供实现的原理和参考代码段,并不提供把该功能设计成组件的相关体系结构和类设计。而关于Ajax push组件的设计笔者正在编写另一篇文章。
回到正题,我们先从客户端谈起,由于Web无状态非连接的特性,如果我们要在web上实现push方式,那么我们首要的是必须与服务器建立通信连接。然而我们要求是不安装任何插件,那我们首先应当想到XmlHttpRequest对象,这个非常对,那么我们如何它与服务器建立连接呢?很简单,由于该通信连接不能阻塞浏