您好,欢迎访问一九零五行业门户网

JavaScript中一些web通信知识点总结(分享)

web通信,一个特别大的topic,涉及面也是很广的。因最近学习了 javascript 中一些 web 通信知识,在这里总结下。
一、前言
1、comet技术
浏览器作为 web 应用的前台,自身的处理功能比较有限。浏览器的发展需要客户端升级软件,同时由于客户端浏览器软件的多样性,在某种意义上,也影响了浏览器新技术的推广。
在 web 应用中,浏览器的主要工作是发送请求、解析服务器返回的信息以不同的风格显示。ajax 是浏览器技术发展的成果,通过在浏览器端发送异步请求,提高了单用户操作的响应性。
但 web 本质上是一个多用户的系统,对任何用户来说,可以认为服务器是另外一个用户。现有 ajax 技术的发展并不能解决在一个多用户的 web 应用中,将更新的信息实时传送给客户端,从而用户可能在“过时”的信息下进行操作。而 ajax 的应用又使后台数据更新更加频繁成为可能。
随着互联网的发展,web 应用层出不穷,也不乏各种网站监控、即时报价、即时通讯系统,为了让用户得到更好的体验,服务器需要频繁的向客户端推送信息。
开发者一般会采用基于 ajax 的长轮询方式或者基于 iframe 及 htmlfile 的流方式处理。当然有些程序需要在客户端安装各种插件( java applet 或者 flash )来支持性能比较良好的“推”信息。
2. http协议中的长、短连接
短连接的操作步骤是:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接
长连接的操作步骤是:建立连接——数据传输...(保持连接)...数据传输——关闭连接
长连接与短连接的不同主要在于client和server采取的关闭策略不同。短连接在建立连接以后只进行一次数据传输就关闭连接,而长连接在建立连接以后会进行多次数据数据传输直至关闭连接(长连接中关闭连接通过connection:closed头部字段)。
二、web 通信
首先要搞清楚,xhr 的 readystate 各种状态。
1.轮询
轮询是一种“拉”取信息的工作模式。设置一个定时器,定时询问服务器是否有信息,每次建立连接传输数据之后,链接会关闭。
前端实现:
var polling = function(url, type, data){    var xhr = new xmlhttprequest(),         type = type || get,        data = data || null;    xhr.onreadystatechange = function(){        if(xhr.readystate == 4) {            receive(xhr.responsetext);            xhr.onreadystatechange = null;        }    };    xhr.open(type, url, true);    //ie的activexobject(microsoft.xmlhttp)支持get方法发送数据,    //其它浏览器不支持,已测试验证    xhr.send(type == get ? null : data);};var timer = setinterval(function(){    polling();}, 1000);
在轮询的过程中,如果因为网络原因,导致上一个 xhr 对象还没传输完毕,定时器已经开始了下一个询问,上一次的传输是否还会在队列中,这个问题我没去研究。如果感兴趣可以自己写一个ajax的请求管理队列。
2.长轮询(long-polling)
长轮询其实也没啥特殊的地方,就是在xhr对象关闭连接的时候马上又给他接上~ 看码:
var longpoll = function(type, url){    var xhr = new xmlhttprequest();    xhr.onreadystatechange = function(){        // 状态为 4,数据传输完毕,重新连接        if(xhr.readystate == 4) {            receive(xhr.responsetext);            xhr.onreadystatechange = null;            longpoll(type, url);        }    };    xhr.open(type, url, true);    xhr.send();}
只要服务器断开连接,客户端马上连接,不让他有一刻的休息时间,这就是长轮询。
3.数据流
数据流方式,在建立的连接断开之前,也就是 readystate 状态为 3 的时候接受数据,但是麻烦的事情也在这里,因为数据正在传输,你拿到的 xhr.response 可能就是半截数据,最好定义一个数据传输的协议,比如前2个字节表示字符串的长度,然后你只获取这个长度的内容,接着改变游标的位置。
假如数据格式为: data splitchar   data为数据内容,splitchar为数据结束标志(长度为1)。 那么传输的数据内容为 data splitchar data splitchar data splitchar...
var datastream = function(type, url){    var xhr = new xmlhttprequest();    xhr.onreadystatechange = function(){        // 状态为 3,数据接收中        if(xhr.readystate == 3) {            var i, l, s;            s = xhr.response; //读取数据            l = s.length;     //获取数据长度            //从游标位置开始获取数据,并用分割数据            s = s.slice(p, l - 1).split(splitchar);            //循环并操作数据            for(i in s) if(s[i])  deal(s[i]);            p = l;  //更新游标位置        }        // 状态为 4,数据传输完毕,重新连接        if(xhr.readystate == 4) {            xhr.onreadystatechange = null;            datastream(type, url);        }    };    xhr.open(type, url, true);    xhr.send();};
这个代码写的是存在问题的,当readystate为3的时候可以获取数据,但是这时获取的数据可能只是整体数据的一部分,那后半截就拿不到了。
readystate在数据传输完毕之前是不会改变的,也就是说他并不会继续接受剩下的数据。我们可以定时去监听readystate,这个下面的例子中可以看到。
这样的处理不算复杂,但是存在问题。上面的轮询和长轮询是所有浏览器都支持的,所以我就没有写兼容ie的代码,但是这里,低版本ie不允许在readystate为3的时候读取数据,所以我们必须采用其他的方式来实现。
在ajax还没有进入web专题之前,我们已经拥有了一个法宝,那就是iframe,利用iframe照样可以异步获取数据,对于低版本ie可以使用iframe来接受数据流。
if(isie){    var datastream = function(url){        var ifr = document.createelement(iframe), doc, timer;        ifr.src = url;        document.body.appendchild(ifr);        doc = ifr.contentwindow.document;        timer = setinterval(function(){            if(ifr.readystate == interactive){                // 处理数据,同上            }            // 重新建立链接            if(ifr.readystate == complete){                clearinterval(timer);                datastream(url);            }        }, 16);    };};
定时去监听iframe的readystate的变化,从而获取数据流,不过,上面的处理方式还是存在问题。数据流实现“服务器推”数据的原理是什么呢,就是文档(数据)还没有加载完,这个时候浏览器的工作就是去服务器拿数据完成文档(数据)加载。
所以上述利用iframe的方式获取数据,会使浏览器一直处于加载状态,title上的那个圈圈一直在转动,鼠标的状态也是loading,这看着是相当不爽的。
幸好,ie提供了htmlfile对象,这个对象就相当于一个内存中的document对象,它会解析文档。所以我们创建一个htmlfile对象,在里面放置一个iframe来连接服务器。这样,各种浏览器就都支持了。
if(isie){    var datastream = function(url){        var doc = new activexobject(htmlfile),             ifr = doc.createelement(iframe),             timer, d;        doc.write(<body/>);        ifr.src = url;        doc.body.appendchild(ifr);        d = ifr.contentwindow.document;        timer = setinterval(function(){            if(d.readystate == interactive){                // 处理数据,同上            }            // 重新建立链接            if(d.readystate == complete){                clearinterval(timer);                datastream(url);            }        }, 16);    };};
4.websocket
websocket是前端一个神器,ajax用了这么久了,相关技术也是很成熟,不过要实现个数据的拉取确实十分不易,从上面的代码中也看到了,各种兼容性问题,各种细节处理问题。
var ws = new websocket(ws://www.example.com:8888);ws.onopen = function(evt){};ws.onmessage = function(evt){    deal(evt.data);};ws.onclose  = function(evt){};//ws.close();
新建一个websocket实例,一切就ok了,ws:// 是websocket的连接协议,8888为端口号码。onmessage中提供了data这个属性,相当方便
5.eventsource
html5中提供的eventsource这玩意儿,这是无比简洁的服务器推送信息的接受函数。
new eventsource(test.php).onmessage=function(evt){    console.log(evt.data);};
简洁程度和websocket是一样的啦,只是这里有一个需要注意的地方,test.php输出的数据流应该是特殊的mime类型,要求是text/event-stream,如果不设置的话,你试试~ (直接抛出异常)
6.actionscript
情非得已就别考虑这第六种方式了,虽说兼容性最好,要是不懂as,出了点bug你也不会调试。
具体实现方法:在 html 页面中内嵌入一个使用了 xmlsocket 类的 flash 程序。javascript 通过调用此 flash 程序提供的套接口接口与服务器端的套接口进行通信。javascript 在收到服务器端以 xml 格式传送的信息后可以很容易地控制 html 页面的内容显示。
7.java applet套接口
三、后端处理方式
本文主要是总结javascript的各种通讯方式,后端配合node来处理,应该是挺给力的。
var conns = new array();var ws = require(websocket-server);var server = ws.createserver();server.addlistener(connection, function(connection){  console.log(connection request on websocket-server);  conns.push(connection);  connection.addlistener('message',function(msg){        console.log(msg);        for(var i=0; i 下面是一个php的测试demo。
header('content-type:text/html; charset=utf-8');while(1){    echo date('y-m-d h:i:s');    flush();    sleep(1);};
四、web 通信方式利弊分析
轮询,这种方式应该是最没技术含量的,操作起来最方便,不过是及时性不强,把定时器的间隔时间设置的短一些可以稍微得到缓和。
长轮询,算是比较不错的一个web通讯方式,不过每次断开连接,比较耗服务器资源,客户端到无所谓。
数据流,他和长轮询不同之处是接受数据的时间不一样,数据流是readystate为3的时候接受,低版本ie不太兼容,处理起来略麻烦,而且还要自己设计数据传输协议。不过他对资源的消耗比上面几种都可观。
websocket和eventsource,两个利器,不过,没几个浏览器支持,这是比较让人伤心~
actionscript和java applet,两者都是需要在客户端安装插件的,一个是flash插件,一个是java插件,而且搞前端的人一般对这东西不太熟悉,如果没有封装比较好的库可以使用,那建议还是别用了。
更多编程相关知识,请访问:编程视频!!
以上就是javascript中一些web通信知识点总结(分享)的详细内容。
其它类似信息

推荐信息