首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

反向 Ajax,第 1 部分 Comet 简介(3)

反向 Ajax,第 1 部分 Comet 简介(3)

使用 HTTP 长轮询的 Comet长轮询 (long polling) 模式涉及了打开连接的技术。连接由服务器端保持着打开的状态,只要一有事件发生,响应就会被提交,然后连接关闭。接下来。一个新的长轮询连接就会被正在等待新事件到达的客户端重新打开。
您可以使用 script 标签或是单纯的 XMLHttpRequest 对象来实现 HTTP 长轮询。
script 标签正如 iframe 一样,其目标是把 script 标签附加到页面上以让脚本执行。服务器端则会:挂起连接直到有事件发生,接着把脚本内容发送回浏览器,然后重新打开另一个 script 标签来获取下一个事件。
  • 优点:因为是基于 HTML 标签的,所有这一技术非常容易实现,且可跨域工作(默认情况下,XMLHttpRequest 不允许向其他域或是子域发送请求)。
  • 缺点:类似于 iframe 技术,错误处理缺失,您不能获得连接的状态或是有干涉连接的能力。
XMLHttpRequest 长轮询第二种,也是一种推荐的实现 Comet 的做法是打开一个到服务器端的 Ajax 请求然后等待响应。服务器端需要一些特定的功能来允许请求被挂起,只要一有事件发生,服务器端就会在挂起的请求中送回响应并关闭该请求,完全就像是您关闭了 servlet 响应的输出流。然后客户端就会使用这一响应并打开一个新的到服务器端的长生存期的 Ajax 请求,如清单 9清单 9 所示:
清单 9. 清单 9 设置长轮询请求的 JavaScript 代码示例
1
2
3
4
5
6
7
8
function long_polling() {
    $.getJSON('ajax', function(events) {
        processEvents(events);
        long_polling();
    });
}

long_polling();




在后端,代码也是使用 Servlet 3 API 来挂起请求,正如 HTTP 流的做法一样,但是您不需要所有的多部分处理代码。清单 10清单 10 给出了一个例子。
清单 10. 清单 10 挂起一个长轮询 Ajax 请求
1
2
3
4
5
6
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    AsyncContext asyncContext = req.startAsync();
    asyncContext.setTimeout(0);
    asyncContexts.offer(asyncContext);
}




在接收到事件时,只是取出所有的挂起请求并完成它们,如清单 11清单 11 所示:
清单 11. 清单 11 在有事件发生时完成长轮询 Ajax 请求
1
2
3
4
5
6
7
8
9
10
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();
}




在随带的  中,comet-long-polling 文件夹包含了一个长轮询示例 Web 应用,您可以使用 mvn jetty:run 命令来运行它。
  • 优点:客户端很容易实现良好的错误处理系统和超时管理。这一可靠的技术还允许在与服务器端的连接之间有一个往返,即使连接是非持久的(当您的应用有许多的客户端时,这是一件好事)。它可用在所有的浏览器上;您只需要确保所用的 XMLHttpRequest 对象发送到了简单的 Ajax 请求就可以了。
  • 缺点:相比于其他技术来说,不存在什么重要的缺点,像所有我们已经讨论过的技术一样,该方法依然依赖于无状态的 HTTP 连接,其要求服务器端有特殊的功能来临时挂起连接。
建议因为所有现代的浏览器都支持跨域资源共享(Cross-Origin Resource Share,CORS)规范,该规范允许XHR执行跨域请求,因此基于脚本的和基于 iframe 的技术已成为了一种过时的需要。
为反向 Ajax 实现和使用 Comet 的最好方法是通过 XMLHttpRequest 对象,它提供了一个真正的连接句柄和错误处理。考虑到不是所有的浏览器都支持 multi-part 标志,且多部分流可能会遇到缓冲问题,因此建议您选择经由 HTTP 长轮询使用 XMLHttpRequest 对象(在服务器端挂起的一个简单的 Ajax 请求)的 Comet 模式,所有支持 Ajax 的浏览器也都支持该种做法。
返回列表