HTTP长连接实现“服务器推”的技术快速入门及演示示例
2015-08-08 11:30
761 查看
转自:http://blog.csdn.net/xxd851116/article/details/10022015
在我的印象里HTTP是一种“无状态的协议”,也就是不知道以前请求的历史,无法保留上一次请求的结果。
Cookie的诞生,弥补了这个不足,浏览器可以通过本地持久化请求数据来记录上次请求的环境。但这个没有根本上改变HTTP请求本身的这种“客户端请求服务器端相应”模式——客户端是主动的,而服务器是被动的。
最近听说有“HTTP长连接”,去探索了一把,果然很有意思,能够实现“服务器推”的这种概念,也就是服务器是主动发送请求,客户端是被动接受请求。
关于“服务器推”及“HTTP长连接”的概念网上很多,给一个比较系统的介绍文章:
http://www.ibm.com/developerworks/cn/web/wa-lo-comet/
HTTP长连接这种把数据从服务器主动“推”到客户端的技术,能带来的好处不言而喻。它可以把最新的统计数据输出到客户端,也可以实现即时通讯。
下面是JSP实现的一个“监控服务器时间”程序的代码示例(片段)
1、web.xml
[html] view
plaincopy
<servlet>
<servlet-name>ServerTimeMonitorServlet</servlet-name>
<servlet-class>com.ebiz.test.ServerTimeMonitorServlet</servlet-class>
<init-param>
<param-name>interval</param-name>
<param-value>1</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServerTimeMonitorServlet</servlet-name>
<url-pattern>/ServerTimeMonitor</url-pattern>
</servlet-mapping>
2、servlet:ServerTimeMonitorServlet.java
[java] view
plaincopy
package com.ebiz.test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServerTimeMonitorServlet extends HttpServlet {
private static final long serialVersionUID = -3981794330055840248L;
private String interval = "1";
public void init(ServletConfig config) throws ServletException {
this.interval = config.getInitParameter("interval");
super.init();
}
public void destroy() {
this.interval = null;
super.destroy();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
java.io.IOException {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000 * Integer.valueOf(interval));
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss E");
String date_str = df.format(new Date());
writerResponse(response, date_str, "showServerTime");// msg是test.jsp中的那个js方法的名称
}
return;
}
protected void writerResponse(HttpServletResponse response, String body, String client_method) throws IOException {
StringBuffer sb = new StringBuffer();
sb.append("<script type=\"text/javascript\">//<![CDATA[\n");
sb.append(" parent.").append(client_method).append("(\"").append(body).append("\");\n");
sb.append("//]]></script>");
System.out.println(sb.toString());
response.setContentType("text/html;charset=GBK");
response.addHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Cache-Control", "pre-check=0,post-check=0");
response.setDateHeader("Expires", 0);
response.getWriter().write(sb.toString());
response.flushBuffer();
}
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
}
3、jsp:server-time-monitor.jsp
[html] view
plaincopy
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="ctx" value="${pageContext.request['contextPath']}" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTTP 长连接测试 —— 监控服务器时间 </title>
</head>
<body>
<div id="monitor-window">服务器现在是:<span id="time"></span></div>
<form id="a-form" action="${ctx}/ServerTimeMonitor" method="post" target="handleFrame">
<input type="submit" name="submit" id="submit" value=" 获取并监控服务器时间 " />
</form>
<iframe name="handleFrame" id="handleFrame" style="display:none"></iframe>
<!-- <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script> -->
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script type="text/javascript">//<![CDATA[
function showServerTime(msg) {
$("#time").html(msg);
}
//]]></script>
</body>
</html>
执行过程
仔细看JSP这段HTML代码,很有意思。
1、form通过POST请求把返回的Script代码输出到iframe中(form的target="handleFrame")。这段返回的Script代码在服务器的控制台输出如下:
[javascript] view
plaincopy
<script type="text/javascript">//<![CDATA[
parent.showServerTime("2013-08-17 12:08:14 星期六");
//]]></script>
2、iframe完成加载上面这段代码后解析并执行,这段代码的作用是调用父页面的“showServerTime”方法,把消息传入。
3、父页面showServerTime函数负责处理接收到的消息。
4、Servlet负责定时执行和输出,源源不断向客户端发送内容。
原来,这个隐藏的iframe起到了一个“纽带”的作用。
演示结果
测试结果
在Chrome中标题前面有一个正在加载的图标,感觉上页面一直在加载,IE9中没有这个现象,其他浏览器没有测试。
(完)
在我的印象里HTTP是一种“无状态的协议”,也就是不知道以前请求的历史,无法保留上一次请求的结果。
Cookie的诞生,弥补了这个不足,浏览器可以通过本地持久化请求数据来记录上次请求的环境。但这个没有根本上改变HTTP请求本身的这种“客户端请求服务器端相应”模式——客户端是主动的,而服务器是被动的。
最近听说有“HTTP长连接”,去探索了一把,果然很有意思,能够实现“服务器推”的这种概念,也就是服务器是主动发送请求,客户端是被动接受请求。
关于“服务器推”及“HTTP长连接”的概念网上很多,给一个比较系统的介绍文章:
http://www.ibm.com/developerworks/cn/web/wa-lo-comet/
HTTP长连接这种把数据从服务器主动“推”到客户端的技术,能带来的好处不言而喻。它可以把最新的统计数据输出到客户端,也可以实现即时通讯。
下面是JSP实现的一个“监控服务器时间”程序的代码示例(片段)
1、web.xml
[html] view
plaincopy
<servlet>
<servlet-name>ServerTimeMonitorServlet</servlet-name>
<servlet-class>com.ebiz.test.ServerTimeMonitorServlet</servlet-class>
<init-param>
<param-name>interval</param-name>
<param-value>1</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServerTimeMonitorServlet</servlet-name>
<url-pattern>/ServerTimeMonitor</url-pattern>
</servlet-mapping>
2、servlet:ServerTimeMonitorServlet.java
[java] view
plaincopy
package com.ebiz.test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServerTimeMonitorServlet extends HttpServlet {
private static final long serialVersionUID = -3981794330055840248L;
private String interval = "1";
public void init(ServletConfig config) throws ServletException {
this.interval = config.getInitParameter("interval");
super.init();
}
public void destroy() {
this.interval = null;
super.destroy();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
java.io.IOException {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000 * Integer.valueOf(interval));
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss E");
String date_str = df.format(new Date());
writerResponse(response, date_str, "showServerTime");// msg是test.jsp中的那个js方法的名称
}
return;
}
protected void writerResponse(HttpServletResponse response, String body, String client_method) throws IOException {
StringBuffer sb = new StringBuffer();
sb.append("<script type=\"text/javascript\">//<![CDATA[\n");
sb.append(" parent.").append(client_method).append("(\"").append(body).append("\");\n");
sb.append("//]]></script>");
System.out.println(sb.toString());
response.setContentType("text/html;charset=GBK");
response.addHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Cache-Control", "pre-check=0,post-check=0");
response.setDateHeader("Expires", 0);
response.getWriter().write(sb.toString());
response.flushBuffer();
}
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
}
3、jsp:server-time-monitor.jsp
[html] view
plaincopy
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="ctx" value="${pageContext.request['contextPath']}" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTTP 长连接测试 —— 监控服务器时间 </title>
</head>
<body>
<div id="monitor-window">服务器现在是:<span id="time"></span></div>
<form id="a-form" action="${ctx}/ServerTimeMonitor" method="post" target="handleFrame">
<input type="submit" name="submit" id="submit" value=" 获取并监控服务器时间 " />
</form>
<iframe name="handleFrame" id="handleFrame" style="display:none"></iframe>
<!-- <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script> -->
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script type="text/javascript">//<![CDATA[
function showServerTime(msg) {
$("#time").html(msg);
}
//]]></script>
</body>
</html>
执行过程
仔细看JSP这段HTML代码,很有意思。
1、form通过POST请求把返回的Script代码输出到iframe中(form的target="handleFrame")。这段返回的Script代码在服务器的控制台输出如下:
[javascript] view
plaincopy
<script type="text/javascript">//<![CDATA[
parent.showServerTime("2013-08-17 12:08:14 星期六");
//]]></script>
2、iframe完成加载上面这段代码后解析并执行,这段代码的作用是调用父页面的“showServerTime”方法,把消息传入。
3、父页面showServerTime函数负责处理接收到的消息。
4、Servlet负责定时执行和输出,源源不断向客户端发送内容。
原来,这个隐藏的iframe起到了一个“纽带”的作用。
演示结果
测试结果
在Chrome中标题前面有一个正在加载的图标,感觉上页面一直在加载,IE9中没有这个现象,其他浏览器没有测试。
(完)
相关文章推荐
- onfiguration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/security]
- 18个在Linux下监控网络流量的命令(工具)
- Web开发基础知识的整理(一、Http协议的简单介绍)
- 网络编程1
- 随机神经网络之模拟退火
- GO1.5实现简单的http并发请求,支持:GET、POST、HEAD、PUT
- 关于DDOS攻击
- 网络编程2
- UVa 11045 My T-shirt suits me (网络流建图+最大流)
- 【Win10 应用开发】扫描和连接Wi-fi网络
- Java API研究:获取本地环境所有网卡及每个网卡的所有网络配置
- iOS安全系列之一:HTTPS
- Linux-C网络编程之epoll函数
- 进程在多核CPU环境下分布不均导致TCP连接堆积
- tcp/ip三次握手、四次挥手
- 摘自织梦CMS的HTTP文件下载类
- TCP/IP详解学习笔记--TCP数据流
- android------HttpURLConnection用法
- HDU 5006 Resistance (2014年鞍山赛区网络赛J题)
- tcp_wrapper应用简介