本文由大丰哥参考自:

congdepeng博文http://congdepeng.iteye.com/blog/1169481、
stackoverflow问题“What are Long-Polling,Websockets,Server-Sent Events (SSE) and Comet?”Steve ChAmbers的答案
gemantic博文http://gemantic.iteye.com/blog/1553385
李刚《疯狂HTML5/CSS3/Javascript讲义》第18章
MOZILLA DEVELOPER NETWORK文档https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events
小胡子哥博文http://www.cnblogs.com/hustskyking/p/3479336.html
感谢以上诸位前辈。
#什么是Ajax?
异步的JavaScript和XML(AsynchronousJavaScript and XML)。浏览器允许JavaScript脚本向服务器发送一个HTTP请求而又无需重新加载页面。
这个功能主要由浏览器完成,浏览器提供这个功能给JavaScript脚本来调用,然后浏览器根据规则来回调脚本去处理响应。所以Ajax中其实浏览器是最大苦力。JavaScript可以换成其他脚本,交换数据也不一定是XML格式的,所以XML也是可有可无的。所以Ajax中除了A(Asynchronous)以外,其他几个字母都是浮云。

#浏览器是如何封装异步调用功能给JavaScript调用?
浏览器把这个功能封装在一个JavaScript对象 window.XMLHttpRequest 里面。这个对象就像一个代理,为JavaScript调用提供接口。

XMLHttpRequest提供了一些方法以及属性如下:

  • open(method,url,async):调用的参数配置
  • send([string]):将请求发送到服务器
  • onreadystatechange( ):由浏览器回调的方法,由开发人员编写
  • readyStateHTTP请求的状态
  • status:HTTP状态码

浏览器其实只是封装了一个Socket调用而已。XMLHttpRequest作为封装这个Socket的Proxy。


Socket的工作流程:

创建Socket对象--> 建立连接--> 发送数据--> 接受数据--> 处理接受到的数据--> 关闭连接

Ajax的工作流程:

创建XMLHttpRequest对象-->设置连接的相关参数open(method,async)-->发送数据send([string])-->处理接受到的数据onreadystatechange( )


对比Socket和Ajax的工作流程,你会发现经过浏览器封装后的Socket调用更加简单,你不需要主动建立连接和关闭连接,只需要设置好相关的参数,同时写好如何处理接受到的数据的方法,那么关于Socket以及HTTP协议的细节问题就交给浏览器去做了。

Ajax调用的基本代码示例:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
    // xmlhttp.readyState
    // xmlhttp.status
}
xmlhttp.open("GET","/ajax/demo_get.PHP",true);
xmlhttp.send();
Ajax做轮询:
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);

Ajax发送的内容仍然是基于HTTP协议的请求。理论上Ajax发送一个请求和你在地址栏里面输入请求是一模一样的。服务器应该根本就不知道什么是Ajax,服务器只处理HTTP请求。



#什么是Reverse Ajax

先谈谈为什么要Reverse Ajax:

因为HTTP协议是无状态的,即请求完数据后就关闭了连接。如果服务器有新的数据,浏览器是无法知道的,必须主动去查询才能知道。又因为Ajax是基于HTTP的,所以Ajax请求在缺省情况下也是无状态的,且只能从客户端向服务器端发出请求。(可以通过使用技术模拟服务器端和客户端之间的响应式通信来绕过这一限制)。


为了尽快地获得服务器端事件,我们只能使用粗暴的HTTP轮询来完成任务。轮询的间隔(两次请求相隔的时间)必须尽可能地小。

  • 优点:很容易实现,不需要任何服务器端的特定功能,且在所有的浏览器上都能工作。
  • 缺点:如果间隔减小的话,客户端浏览器就会发出更多的请求,这些请求中的许多都不会返回任何有用的数据,而这将会白白地浪费掉带宽和处理资源。


用firebug 调试一下 weibo.com 的网络请求可以发现,微博用的是轮询来实现消息提醒的,应该是用set timer隔个0.7分钟去服务器进行查询。和即时通信的web应用不同,微博提醒实时性要求不高,所以用轮询方式比较合理,没有必要用长连接。


有一个叫捎带轮询(piggyback polling)的实现方式是一种比轮询更加聪明的做法。它会删除掉所有非必需的请求(没有返回数据的请求)。不存在时间间隔,客户端在需要的时候向服务器端发送请求。不同之处在于响应的那部分上,响应被分成两个部分:对请求数据的响应和对服务器事件的响应,如果任何一部分有发生的话,在实现piggyback技术时,通常针对服务器端的所有Ajax请求可能会返回一个混合的响应。

  • 优点:没有不返回数据的请求。因为客户端对何时发送请求做了控制,对资源的消耗较少。该方法也可用在所有的浏览器上,不需要服务器端的特殊功能。
  • 缺点:当累积在服务器端的事件需要传送给客户端时,你却一点都不知道,因为这需要一个客户端行为来请求它们。

我们回到原点,为什么要关闭连接然后再不停的建立连接呢? 为什么不建立一个时间非常长的连接呢?
因为以前的HTTP 1.0不支持长连接,所以我们不得已只能轮询!到了HTTP 1.1开始支持长连接,我们可以建立一个长连接来完成这个目的。下面介绍长连接。

#Comet

Comet 是一种Web应用程序架构。可以说,它不是一种技术,而是一种思想,只是这种思想采用了已有的技术去实现。在这种思想里,客户端(Client)不需要显式地向服务器端(Server)发出请求,Server会在其数据发生变化的时候主动将数据异步发送给Client,从而使Client能够及时更新数据并呈现给用户。它不同于传统的Web,也不同于当前流行的Ajax,这种思想非常架构思想非常适合event-driven(事件驱动)式的Web应用和对交互性及实时性要求很强的应用,比如股票交易,聊天室,Web IM,网游等。


最常见的有下面两种方式:

1. HTTP 长轮询( HTTP Long Polling Javascript 在处理完服务器返回的信息后再次发出请求,重新建立连接。不同于一般的 Ajax Javascript 请求 Server ,无数据时 Server 不中断请求( still loading) ,在一定时间内获取到数据后,返回请求,又在 获取数据后再次发出请求,由此轮询。需要注意的是请求的间隔时间以及每次请求的最长 Loading 时间。做个比喻, 如果 轮询 是排队买东西,那么长轮询就是排队上厕所。买东西的话,丢下钱就可以拿东西走了,但是上厕所就不一样,有些人说不定便秘半个小时都出不来。如果只用轮询去做Web通信,那服务器就鸭梨山大了,它需要一直做接受和断开HTTP请求的操作。就像卖热销产品的店员就没有公共厕所管理员那么轻松。

  • 优点:异步请求;无需浏览器任何插件支持;采用Ajax技术,兼容性强;
  • 缺点:会产生大量的通信量,只能通过增加轮询的时间间隔来减轻Server的压力;

ajax实现长轮询时,就是在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,true);
    xhr.send();
}

只要服务器断开连接,客户端马上连接,不让有一刻的休息时间,这就是长轮询。


2. Iframe结合Htmlfile流(streaming) HTTP 流( HTTP Streaming :通过在页面上嵌入一个隐藏的Iframe,设置其src属性为一个长连接的请求,Server采用flush方式将数据作为前端Javascript函数的参数传递;

  • 优点:不会有很大的通信量,而且数据接收非常及时,并且无中断;
  • 缺点:会产生进度条的Loading状态并一直存在,用户使用体验很不好。在Google Talk中,通过Htmlfile Active解决了IE下的进度条显示问题;保持长期链接也非常耗服务器资源;

反向Ajax的目的是允许服务器端向客户端推送信息。这样如果服务端有数据更新,就可以及时推送给客户端。
#HTML5Server-Sent Events
Server-Sent Events 是一个从服务器到浏览器的单向推送, 实际上是将Comet技术进行了标准化。Server-Sent Events规范“定义了API来打开一个HTTP连接,通过该连接能够获取从服务器推送的通知”。 Server-Sent Events 包含新的 Javascript 对象EventSource 和新的 MIME 类型 text/event-stream,这个 MIME 类型定义了事件框架格式。

EventSource 代表的是接收事件的客户端的终点。客户端通过创建 EventSource 对象来打开一个 event stream。创建 EventSource 对象时,该对象接收一个事件来源的 URI 作为其构造函数的参数。当每次收到新的事件数据时 onmessage 事件处理器会被调用。

Server-Sent Events是基于HTTP streaming的。如上所述,响应会一直打开,当服务器端有事件发生的时候,事件会被写入响应中。


#HTML5 WebSocket

WebSocket 启用了双向的全双工通信信道,许多浏览器(Firefox、Google Chrome 和 Safari)都已对此做了支持。连接会保持在活动状态,可以使用 JavaScript 来写入和接收数据,就像是在使用一个原始的TCP套接口一样。WebSocket URL的起始输入是ws://或是wss://(在SSL上),从这个ws和wss上可以想到,WebSocket已经不是建立在HTTP协议之上了!

  • 优点:功能强大、双向、低延迟,且易于处理错误。不像 Comet 长轮询那样有许多的连接。它的API 也很容易使用,无需另外的层就可以直接使用,而Comet 则需要一个很好的库来处理重连接、超时、Ajax请求、确认以及选择不同的传输(Ajax 长轮询和 jsonp 轮询)。
  • 缺点:是一个来自 HTML5 的新规范,还没有被所有的浏览器支持。没有请求作用域(request scope)(因为WebSocket是一个TCP套接口而不是一个HTTP请求),有作用域的请求服务,比如说 Hibernate 的 SessionInViewFilter,就不太容易使用。
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();

Ajax、服务器推和双向通信的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. 详解html5 postMessage解决跨域通信的问题

    这篇文章主要介绍了详解html5 postMessage解决跨域通信的问题的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. 前端监听websocket消息并实时弹出(实例代码)

    这篇文章主要介绍了前端监听websocket消息并实时弹出,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. html5 http的轮询和Websocket原理

    这篇文章主要介绍了html5 http的轮询和Websocket原理的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. HTML5调用手机发短信和打电话功能

    这篇文章主要介绍了HTML5调用手机发短信和打电话功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. html5简介_动力节点Java学院整理

    这篇文章主要介绍了html5简介,用于指定构建网页的元素,这些元素中的大多数都用于描述网页内容,有兴趣的可以了解一下

  10. 真正的iOS设备和Watch Simulator可以进行通信以进行测试

    我想为现有的iOS应用创建一个手表应用.但我处于一种情况,我没有苹果手表,我现有的iOS应用程序只能在不在模拟器上的真实设备上运行.是否可以在iPhone设备上运行应用程序并在手表模拟器中测试我的手表应用程序?解决方法至少在目前,不可能配对真正的iPhone和Watch模拟器.我得出这个结论有三个原因:>Watch模拟器在安装过程中自动与iPhone模拟器配对.>根本无法从界面取消配对Watch模拟器.>在模拟器上无法访问蓝牙以与真实设备进行通信.这是一个proof.

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到<input>中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部