Comet - 使用 HTTP 长连接、无须浏览器安装插件的两种“服务器推”方案:
1、基于 AJAX 的长轮询方式;
2、基于 iframe 及 htmlfile 的流方式。
开源的 Comet 框架-pushlet,提供了以上两种方式的封装。
Ajax长轮询,客户端发起XMLHttpRequest请求,服务端阻塞请求,直到有数据返回,客户端处理完响应后,断开链接,然后马上重新建立链接。
1、服务器端会阻塞请求直到有数据传递或超时才返回。
2、客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
3、当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。
图 2. 基于长轮询的服务器推模型
基于 Iframe 及 htmlfile 的流(streaming)方式
iframe 是很早就存在的一种 HTML 标记, 通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。
图 3. 基于流方式的服务器推模型
Tomcat6支持Comet,基于Stream方式,提供CometProcessor和CometEvent接口,详情请见
http://tomcat.apache.org/tomcat-6.0-doc/aio.html。注意:servlet实现CometProcessor接口后不用写doGet,doPoset方法,所有事件在BEGIN,READ,END,ERROR方法中实现。
使用tomcat提供的comet api之前,需要增加对NIO的支持,在server.xml里边修改connector:
<connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8080" redirectport="8443" connectiontimeout="20000">
Jetty Comet实现机制
客户端请求挂入,如果当时没有消息,通过Continuation.suspend挂起,也可设置超时时间;当有消息时,Continuation.resume,重新执行原请求,将消息发送出去;请求结束,客户端重新请求挂入;在下一次请求挂入之前,产生的消息可以堆积起来,下一次挂入时,统一发送给客户端。
提供一个简单实现例子:
package cn.restful.jetty;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String greeting = "Hello World!";
public HelloServlet() {
}
public HelloServlet(String greeting) {
this.greeting = greeting;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
* 挂起,之后doGet会被重新调用一次,内容会被写出两遍,即doGet执行两次,至此请求结束;
* 但不知为何jetty又自动触发了一次target为favicon.ico的请求,doGet又两次被触发,但没有内容输出;
* 原因是:浏览器自动请求的,favicon.ico;把servlet对应的地址修改,不请求根地址就不会触发
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("Start----"+System.currentTimeMillis());
Continuation cc = ContinuationSupport.getContinuation(request);
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>" + greeting + "</h1>");
response.getWriter().println("<h1>" + "pan" + "</h1>");
if(cc.isInitial()){
System.out.println("Suspend----"+System.currentTimeMillis());
/*
* 要实现真正的comet,应该在产生向请求者发送的消息时,resume该请求将消息发送出去
* timeout作为长时间没有消息时的超时设定,心跳
* 在用户请求未进来时,发送的待推送消息,应该堆积等待请求到达并发送出去
*/
cc.setTimeout(5000);
cc.suspend();
}
System.out.println("After suspend----"+System.currentTimeMillis());
response.getWriter().println(
"session=" + request.getSession(true).getId());
// response.getWriter().println("<h1>" + "zhexin" + "</h1>");
response.getWriter().flush();//加flush内容一部分先被刷出,否则请求完成时,一起刷出
try {
if(cc.isSuspended()){//模拟消息到达,触发resume
Thread.sleep(1000);
System.out.println("before resume----"+System.currentTimeMillis());
cc.resume();
System.out.println("after resume----"+System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Process the HTTP Post request
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
System.out.println("doPost----"+System.currentTimeMillis());
doGet(request, response);
}
}
package cn.restful.jetty;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
/**
* @Title: TestServletServer.java
* @Package com.ddz.web.test
* @Description: TODO(jetty嵌入式容器,并验证了下jetty continucation实现comet的方式)
* @author Potter
* @date 2013-12-13 上午11:32:27
* @version V2.0
*/
public class TestServletServer {
public static void main(String[] args) throws Exception{
Server server=new Server(8080);
//第一种方式:通过构造函数,设置默认的session
ServletContextHandler context=new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
//第二种方式:设置session
//Create the SessionHandler (wrapper) to handle the sessions
/*HashSessionManager manager = new HashSessionManager();
SessionHandler sessions = new SessionHandler(manager);
context.setHandler(sessions);*/
context.addServlet(new ServletHolder(new HelloServlet()), "/test/*");
server.start();
server.join();
}
}
- 大小: 16.7 KB
- 大小: 11.4 KB
分享到:
相关推荐
总的来说,这份“学习笔记 MHT3”集合了丰富的学习资源,涵盖Comet技术、Java基础、JavaScript进阶和Spring框架的高级应用,适合正在学习和提升这些技术的开发者进行深入研究。通过系统地学习和实践,可以增强开发者...
Comet.ml-机器学习实验管理 我们的Misson: Comet在为ML做着GitHub在做代码方面的工作。 我们允许数据科学团队自动跟踪其数据集,代码更改,实验历史和生产模型,从而提高效率,透明度和可重复性。 我们都力争在...
DWR学习资料 :DWR 3.0 上传文件.txt DWR3.0反向Ajax示例.txt DWR3.0学习笔记.txt DWR3.0学习网址.txt dwr分页.doc DWR分页代码.doc DWR中文文档.doc DWR中文文档.pdf dwr做comet的完整实现.doc Spring整合DWR comet ...
本笔记将深入探讨DWR的核心概念、工作原理以及实际应用。 一、DWR简介 DWR的主要目标是消除传统的HTTP请求-响应模式的局限性,提供一种更加高效、灵活的远程调用机制。通过DWR,开发者可以在浏览器中编写JavaScript...
【描述】"PyTorch学习日志,深度学习资源整理" 暗示了作者在学习过程中积累的经验和资料,可能包含了笔记、代码示例、问题解答和项目实践等。深度学习是一种模仿人脑神经网络结构的机器学习技术,广泛应用于图像识别...
【标题】:“openfire+smack开发webim笔记”涉及的知识点详解 【一】XMPP(可扩展消息处理现场协议) XMPP是一种基于XML的即时通讯协议,它最初源于Jabber项目,用于实现服务器之间的即时消息传递和在线状态探测。...
浩浩学习,天天向上。数学网课推荐的免费视频~~~ 此笔记与其线代网课相对应 如有遗漏或错误欢迎推PR或发Issue~ 欢迎补充完善:snowman_without_snow:~ PC端推荐使用【Ctrl】+【F】进行关键字定位 推荐 :snake: 想学...
:comet:源码学习 博客 :ant:数据结构与算法 :spider:设计模式 :honeybee:Javascript 语言标准 函数式编程 :butterfly:Nodejs Nest :lady_beetle:TypeScript :lizard:Vue :dolphin:React react :mobile_phone:跨端...
总的来说,这个学习笔记涵盖了JavaScript的基础知识、Ajax编程、jQuery框架以及相关插件的使用,为深入理解和实践JavaScript提供了坚实的基础。无论是前端开发还是全栈开发,掌握这些技能都是非常重要的。
"前端"、"nodejs"、"jsp自定义标签"这些文件夹名则直接对应了上述的技术领域,可能包含了相关的示例代码、教程或者笔记。综合来看,这个压缩包可能是为了分享或备份关于这些技术的学习资料和实践案例。
**PushTest6**:这个文件可能是演示如何实现服务器推(Server-Sent Events或Comet技术)的一个例子。在BlazeDS中,可以通过`PushService`来实现实时数据推送。`PushTest6`可能包含了Flex客户端的源代码,用于订阅...
:sparkles:如何实现一个通用的“划词高亮”在线笔记功能?:sparkles::crayon: 前端跨页面通信,你知道哪些方法? MongoDB高可用__使用Replica Set 各类“服务器推”技术原理与实例(Polling/COMET/SSE/WebSocket) ...
总之,ASP网上聊天室的设计是一个综合性的Web开发项目,涵盖了服务器端脚本、数据库操作、实时通信等多个技术领域,是学习和提升ASP编程技能的好实践。通过深入研究这个项目,不仅可以理解ASP的工作原理,还能掌握...