彗星http

在过去的几年中,Web开发有了长足的发展。 我们超越了链接在一起的静态网页,这导致浏览器刷新并等待页面加载。 现在,需求是可以从Web访问的完全动态的应用程序。 这些应用程序通常需要尽可能快并提供几乎实时的组件。 在这个由五部分组成的新系列中,学习如何使用反向Ajax技术开发事件驱动的Web应用程序。

在第一篇文章中,了解反向Ajax,轮询,流,Comet和长轮询。 了解如何实现不同的Reverse Ajax通信技术,并探讨每种方法的优缺点。 您可以下载源代码以遵循本文中的示例。

Ajax,反向Ajax和WebSockets

异步JavaScript和XML(Ajax),一种可在JavaScript中访问的浏览器功能,允许脚本向幕后的网站发出HTTP请求,而无需重新加载页面。 Ajax已有十多年的历史了。 尽管名称包括XML,但是您几乎可以在Ajax请求中传输任何内容。 最常用的数据是JSON,它接近JavaScript语法并且消耗的带宽更少。 清单1显示了一个Ajax请求示例,该请求从其邮政编码中检索一个地点的名称。

清单1.示例Ajax请求
var url = 'http://www.geonames.org/postalCodeLookupJSON?postalcode=' + $('#postalCode').val() + '&country=' + $('#country').val() + '&callback=?';
$.getJSON(url, function(data) { $('#placeName').val(data.postalcodes[0].placeName);
});

您可以在本文的可下载源代码中的listing1.html中看到此示例工作。

反向Ajax本质上是一个概念:能够从服务器向客户端发送数据。 在标准HTTP Ajax请求中,数据被发送到服务器。 可以通过本文中介绍的特定方式模拟反向Ajax发出Ajax请求,以便服务器可以尽快将事件发送给客户端(低延迟通信)。

来自HTML5的WebSockets是一种更新得多的技术。 许多浏览器已经支持它(Firefox,Google Chrome,Safari和其他)。 WebSockets启用双向全双工通信通道。 该连接是通过一种称为WebSocket握手的HTTP请求打开的,带有一些特殊的标头。 连接保持活动状态,您可以使用JavaScript编写和接收数据,就像使用原始TCP套接字一样。 WebSocket将在本系列的第2部分中得到更多介绍。

反向Ajax技术

反向Ajax的目标是让服务器将信息推送到客户端。 默认情况下,Ajax请求是无状态的,并且只能从客户端打开到服务器。 您可以通过使用模拟服务器和客户端之间响应式通信的技术来绕过此限制。

HTTP轮询和JSONP轮询

轮询涉及从客户端向服务器发出请求以请求一些数据。 这显然只是一个Ajax HTTP请求。 为了尽快获取服务器事件,轮询间隔(请求之间的时间)必须尽可能短。 有一个缺点:如果缩短此间隔,则客户端浏览器将发出更多请求,其中许多请求将不会返回任何有用的数据,并且会浪费带宽和处理资源而无所作为。

图1中的时间轴显示了客户端发出的一些轮询请求如何返回但没有信息。 客户端必须等待下一次轮询才能获取服务器接收到的两个事件。

图1.具有HTTP轮询的反向Ajax

JSONP轮询本质上与HTTP轮询相同。 但是,区别在于,使用JSONP可以发出跨域请求(请求不在您的域中)。 清单1中使用JSONP从邮政编码获取地名。 JSONP请求通常可以通过其回调参数和返回的内容(可执行JavaScript代码)来识别。

要在JavaScript中实现轮询,可以使用setInterval定期发出Ajax请求,如清单2所示:

清单2. JavaScript轮询
setInterval(function() { $.getJSON('events', function(events) { console.log(events); });
}, 2000);

文章源代码中的轮询演示通过轮询方法显示了带宽消耗。 间隔很短,但是您可以看到一些请求不返回任何事件。 清单3显示了示例轮询的输出。

清单3.示例轮询演示输出
[client] checking for events...
[client] no event
[client] checking for events...
[client] 2 events
[event] At Sun Jun 05 15:17:14 EDT 2011
[event] At Sun Jun 05 15:17:14 EDT 2011
[client] checking for events...
[client] 1 events
[event] At Sun Jun 05 15:17:16 EDT 2011

使用JavaScript进行轮询有其优点和缺点。

  • 优点:它非常容易实现,并且不需要服务器端的任何特殊功能。 它也适用于所有浏览器。
  • 缺点:这种方法很少使用,因为它根本无法扩展。 想象一下,如果有100个客户端每个发出轮询请求2秒钟,其中30%的请求未返回数据,则带宽和资源的损失量。

背back式

ggy带式轮询比轮询更聪明,因为它倾向于删除所有不需要的请求(不返回任何数据)。 没有间隔; 当客户端需要向服务器发送请求时,发送请求。 区别在于响应,该响应分为两部分:请求的数据的响应和服务器事件(如果有的话)。 图2显示了一个示例。

图2.带有背负式轮询的反向Ajax

在实施搭载技术时,通常,所有针对服务器的Ajax请求都可能返回混合响应。 文章下载和下面的清单4中提供了一个实现示例。

清单4.示例附带代码
$('#submit').click(function() { $.post('ajax', function(data) { var valid = data.formValid; // process validation results // then process the other part of the response (events) processEvents(data.events); });
});

清单5显示了一些搭载输出。

清单5.附带示例输出
[client] checking for events...
[server] form valid ? true
[client] 4 events
[event] At Sun Jun 05 16:08:32 EDT 2011
[event] At Sun Jun 05 16:08:34 EDT 2011
[event] At Sun Jun 05 16:08:34 EDT 2011
[event] At Sun Jun 05 16:08:37 EDT 2011

您可以看到表单验证的结果以及附加到响应的事件。 同样,该方法也有优点和缺点。

  • 优点:在没有请求不返回数据的情况下,由于客户端控制发送请求的时间,因此资源消耗更少。 它也适用于所有浏览器,并且不需要服务器端的特殊功能。
  • 缺点:您不知道何时将在服务器端累积的事件传递给客户端,因为它需要客户端动作来请求它们。

彗星

带有轮询或背负的反向Ajax非常有限:它不能扩展并且不提供低延迟通信(当事件一到达服务器就到达浏览器)。 Comet是一种Web应用程序模型,在该模型中,请求被发送到服务器并保持很长一段时间,直到发生超时或服务器事件。 请求完成后,将发送另一个长期存在的Ajax请求,以等待其他服务器事件。 使用Comet,Web服务器可以将数据发送到客户端,而无需显式请求它。

Comet的最大优势在于,每个客户端始终都有一条通向服务器的通信链接。 服务器可以通过在客户端到达时立即提交(完成)响应来在客户端上推送事件,或者甚至可以累积并发送突发。 由于请求长时间保持打开状态,因此服务器端需要特殊功能来处理所有这些长期存在的请求。 图3显示了一个示例。 (本系列的第2部分将更详细地说明服务器约束。)

图3.带有彗星的反向Ajax

Comet的实现可以分为两种类型:使用流模式的实现和使用长轮询的实现 。

使用HTTP流的彗星

在流模式下,将打开一个持久连接。 因为到达服务器端的每个事件都是通过同一连接发送的,所以只有一个长期请求( 图3中的 #1)。 因此,它在客户端需要一种方法来分离通过同一连接的不同响应。 从技术上讲,两种常见的流技术包括Forever Iframe(隐藏的IFrame)或XMLHttpRequest对象的多部分功能,用于在JavaScript中创建Ajax请求。

永远的iframe

Forever Iframes技术涉及在页面中放置一个隐藏的Iframe标签,其src属性指向返回服务器事件的servlet路径。 每次接收到一个事件时,该servlet都会编写并刷新其中包含JavaScript代码的新脚本标签。 iframe内容将被附加此脚本标记,该脚本标记将被执行。

  • 优点:易于实现,并且可以在所有支持iframe的浏览器中使用。
  • 缺点:无法实现可靠的错误处理或跟踪连接状态,因为所有连接和数据均由浏览器通过HTML标签处理。 然后,您不知道连接的两端何时断开。

多部分XMLHttpRequest

第二种更为可靠的技术是在XMLHttpRequest对象上使用某些浏览器(例如Firefox)支持的多部分标志。 发送Ajax请求,并在服务器端保持打开状态。 每次事件到来时,都会通过相同的连接写入多部分响应。 清单6显示了一个示例。

清单6.设置多部分流请求的示例JavaScript代码
var xhr = $.ajaxSettings.xhr();
xhr.multipart = true;
xhr.open('GET', 'ajax', true);
xhr.onreadystatechange = function() { if (xhr.readyState == 4) { processEvents($.parseJSON(xhr.responseText)); }
};
xhr.send(null);

在服务器端,情况有些复杂。 您必须首先设置多部分请求,然后暂停连接。 清单7显示了如何暂停HTTP流请求。 (本系列的第3部分将更详细地介绍API。)

清单7.使用Servlet 3 API在Servlet中挂起HTTP流请求
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // start the suspension of the requestAsyncContext asyncContext = req.startAsync(); asyncContext.setTimeout(0); // send the multipart separator back to the clientresp.setContentType("multipart/x-mixed-replace;boundary=\""+ boundary + "\""); resp.setHeader("Connection", "keep-alive"); resp.getOutputStream().print("--" + boundary); resp.flushBuffer(); // put the async context in a list for future usageasyncContexts.offer(asyncContext);
}

现在,每次事件发生时,您都可以遍历所有挂起的连接并将数据写入它们,如清单8所示:

清单8.使用Servlet 3 API将事件发送到暂停的多部分请求
for (AsyncContext asyncContext : asyncContexts) { HttpServletResponse peer = (HttpServletResponse) asyncContext.getResponse(); peer.getOutputStream().println("Content-Type: application/json"); peer.getOutputStream().println(); peer.getOutputStream().println(new JSONArray().put("At " + new Date()).toString()); peer.getOutputStream().println("--" + boundary); peer.flushBuffer();
}

您可以通过本文下载的文件演示了Comet-streaming文件夹中的HTTP流。 运行示例并打开主页时,您将看到事件一到达服务器便立即异步异步出现。 另外,如果打开Firebug控制台,则可以看到仅打开了一个Ajax请求。 如果您更深入地看,您将在Response选项卡中看到JSON响应,如图4所示:

图4. HTTP流请求的FireBug视图

像往常一样,有优点和缺点。

  • 优点:仅打开一个持久连接。 这是彗星技术,可以节省最多的带宽使用。
  • 缺点:不是所有浏览器都支持多部分标志。 一些广泛使用的库(例如Java中的CometD)报告了缓冲问题。 例如,仅在连接完成或缓冲区已满时才可以缓冲并发送数据块(多部分),这可能会产生比预期更高的延迟。

使用HTTP长轮询的Comet

长轮询模式涉及打开连接的技术。 服务器将保持连接的打开状态,一旦发生事件,将提交响应并关闭连接。 然后,客户端会立即重新打开新的长轮询连接,以等待新事件到达。

您可以使用脚本标记或仅XMLHttpRequest对象来实现HTTP长轮询。

脚本标签

与iframe一样,目标是在页面中附加一个脚本代码以使脚本得以执行。 服务器将:暂停连接直到发生事件,将脚本内容发送回浏览器,然后重新打开另一个脚本标签以获取下一个事件。

  • 优点:由于该技术基于HTML标签,因此非常易于实现并且可以跨域使用(默认情况下, XMLHttpRequest不允许在其他域或子域上进行请求)。
  • 缺点:与iframe技术类似,缺少错误处理,并且您无法具有状态或中断连接的能力。

XMLHttpRequest长轮询

推荐的第二个实现Comet的方法是向服务器打开Ajax请求,然后等待响应。 服务器需要服务器端具有特定功能才能暂停请求。 一旦事件发生,服务器就将挂起的请求中的响应发送回并关闭它,就像关闭Servlet响应的输出流一样。 然后,客户机使用响应并向服务器打开一个新的长期Ajax请求,如清单9所示:

清单9.用于设置长轮询请求的示例JavaScript代码
function long_polling() { $.getJSON('ajax', function(events) { processEvents(events); long_polling(); });
} long_polling();

在后端,该代码还使用Servlet 3 API来暂停请求,就像在HTTP流中一样,但是您不需要所有的多部分处理代码。 清单10显示了一个示例。

清单10.暂停长时间轮询的Ajax请求
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AsyncContext asyncContext = req.startAsync(); asyncContext.setTimeout(0); asyncContexts.offer(asyncContext);
}

收到事件后,只需处理所有暂停的请求并完成它们,如清单11所示:

清单11.发生事件时完成长时间轮询的Ajax请求
while (!asyncContexts.isEmpty()) { AsyncContext asyncContext = asyncContexts.poll(); HttpServletResponse peer = (HttpServletResponse) asyncContext.getResponse(); peer.getWriter().write(new JSONArray().put("At " + new Date()).toString()); peer.setStatus(HttpServletResponse.SC_OK); peer.setContentType("application/json"); asyncContext.complete();
}

在随附的可下载源文件中 ,彗星长轮询文件夹包含一个长轮询示例Web应用程序,您可以使用mvn jetty:run命令运行该应用程序。

  • 优点:良好的错误处理系统和超时管理可在客户端轻松实现。 这种可靠的技术还允许服务器端连接之间的往返,因为连接不是持久性的(当您的应用程序上有很多客户端时,这是一件好事)。 它也适用于所有浏览器。 您仅通过发出简单的Ajax请求来使用XMLHttpRequest对象。
  • 缺点:与其他技术相比,没有主要缺点。 但是,就像我们讨论过的所有技术一样,该技术仍然依赖于无状态HTTP连接,该连接需要服务器端的特殊功能才能暂时挂起它。

推荐建议

由于所有现代浏览器都支持跨域资源共享(CORS)规范,该规范允许XHR执行跨域请求,因此不再需要基于脚本和基于iframe的技术。

为反向Ajax实现和使用Comet的最佳方法是通过XMLHttpRequest对象,该对象提供了真正的连接句柄和错误处理。 考虑到并非所有浏览器都支持多部分标志,并且多部分流可能会遇到缓冲问题,因此建议您通过HTTP长轮询将Comet与XMLHttpRequest对象一起使用(服务器上已挂起的简单Ajax请求)侧)。 所有支持Ajax的浏览器也都支持此方法。

结论

本文介绍了反向Ajax技术。 它探索了实现反向Ajax通信的不同方法,并解释了每种实现的优点和缺点。 您的特定情况和应用程序要求将影响哪种方法最适合您。 但是总的来说,如果需要最大的折衷,Comet与Ajax长轮询请求是最好的选择。 超时和错误检测; 简单; 并获得所有浏览器和平台的良好支持。

请继续关注本系列的第2部分,它将探讨第三种反向Ajax技术:WebSockets。 尽管并不是所有的浏览器都支持它,但是WebSockets绝对是Reverse Ajax的一种很好的通信媒介。 WebSocket将删除所有与HTTP连接的无状态特性相关的约束。 第2部分还将介绍由Comet和WebSocket技术引起的服务器端约束。


翻译自: https://www.ibm.com/developerworks/web/library/wa-reverseajax1/index.html

彗星http

彗星http_彗星介绍相关推荐

  1. 彗星http_大气与彗星

    彗星http 本系列向您展示如何使用反向Ajax技术开发事件驱动的Web应用程序. 第1部分介绍了反向Ajax,轮询,流传输,Comet和长轮询. 第2部分解释了如何使用WebSockets实现反向A ...

  2. 彗星http_项目彗星

    彗星http 作者 克里斯·科耶尔 已发表 2015年10月7日 翻译自: https://css-tricks.com/project-comet/ 彗星http

  3. linux下安装虚拟天文馆,如何在Ubuntu 20.04、18.04中安装Stellarium 0.20.0虚拟天文馆

    如何在Ubuntu 20.04.18.04中安装Stellarium 0.20.0虚拟天文馆 几天前发布了Stellarium 0.20.0,它时一个免费开源的桌面虚拟天文馆软件.以下是在Ubuntu ...

  4. 2009壮观天文照片:超大黑洞喷射各种物质

    新浪科技讯 北京时间1月12日消息,据国外媒体报道,2009年是国际天文年,这一年人类取得了许多重大天文进展.以下一组图片将对2009年人类在天文观测和天文学领域的活动进行回顾.[高清图集] 1. 宇 ...

  5. COMET彗星(一)SERVER PUSH介绍

    COMET介绍: 还在为AJAX赞叹的时候,COMET竟也悄悄降临,更有甚者已经将COMET比作是AJAX的接班人.暂且不考虑服务性能和维持connection的负担,COMET的日益走红,让SERV ...

  6. COMET彗星(三)构建自己的COMET核心

    主题列表: COMET彗星(一)SERVER PUSH介绍 COMET彗星(二)基于SERVER PUSH的消息传输 引言: 在上一篇随笔中,对COMET使用的类和作用进行了简短的介绍,从本篇随笔开始 ...

  7. lol无限火力服务器卡顿,LOL无限火力无限彗星BUG是什么? 无限彗星超强卡BUG技巧Get起来...

    :原标题:LOL无限火力无限彗星BUG是什么? 无限彗星超强卡BUG技巧Get起来 英雄联盟2019新春上线了无限乱斗模式,大家又可以在游戏中体现无限火力的乐趣了,但这次无限乱斗模式上线多久呢?什么时 ...

  8. I9 9900K线程_彗星降落人间——Intel第十代台式机酷睿处理器评测之I9篇

    14纳米的彗星湖 在2018年底时写9900K的评测中曾经说过这样一句话:Intel的9900K几乎榨干了目前我们所能看见14nm工艺的全部余韵.当时认为14nm已经用了好几代,按照以往的步骤早就该换 ...

  9. 一生只见一次的大彗星今天来了!

    一生只见一次的大彗星今天来了!编号为C/2011L4的非周期彗星将于今天过近日点.天文专家表示,如果天气晴朗,中国公众用肉眼可在今天日落后和明天日出前观测它的真容.该彗星远离地球后将不会再回归太阳附近 ...

最新文章

  1. python 自动化对比返回结果
  2. Matlab画地球剖面图,分享用matlab显示地震记录的波形变面积图
  3. 遗传算法(Genetic Algorithm )+C++实现解决TSP问题
  4. ios 从assets加载图片_Flutter图片添加水印功能,Flutter保存Widget为图片
  5. android 自定义图片上传,android自定义ImageView仿图片上传(示例代码)
  6. redis api-hash
  7. CPU为什么是方形而不是圆形的?
  8. mac securecrt程序无响应_如何重置mac上的系统管理控制器smc教程
  9. Flask 蓝图机制及应用
  10. UUIDGenerator
  11. android 数组赋值字符串_给字符数组赋值的方法
  12. 进程的同步、互斥、通信的区别,进程与线程同步的区别
  13. 学c语言前要学计算机导论吗,计算机导论与C语言
  14. 监听Dom节点失焦触发方法的几个思路
  15. 比较两条曲线的相似程度
  16. centos 硬盘分区容量调整
  17. 阿龙的学习笔记---哈希表与C++11中unordered_map学习笔记
  18. 怎么把大的文件传送到服务器,大文件如何上传到云服务器
  19. 估算负反馈运算放大电路的闭环电压放大倍数
  20. 修改Win10某种文件类型的默认图标

热门文章

  1. 双守护进程保护程序运行
  2. php cgi远程控制,php cgi远程任意代码执行漏洞
  3. Excel如何在整个工作簿中批量替换指定数据
  4. 【ULR #2】Picks loves segment tree IX
  5. django ulr中配置name的作用
  6. Automating Parallelism
  7. SSH配置和安装,花生壳配置内网穿透,解决服务器拒绝了密码的问题
  8. matlab设置固定的窗宽窗位,【经验谈】如何设定窗宽窗位,附正常人体组织CT值...
  9. 数据仓库系列(二)哲学建模的艺术:如何完成数仓的维度建模设计??--做好宏观角度考虑维度一致性
  10. 如何迎战思科?国外对手扛不住华为的杀价游戏