服务器推技术研究Comet
服务器推技术
最近参与的一个关于股票的项目,有这样一个需求。服务器需要主动推送给客户端消息。这和传统的Web模式不同。传统的Web系统,客户端和服务器的交互是这样的:
客户端先和服务器建立一个TCP连接,然后客户端开始发送数据,服务器端接受数据,并且根据请求去反馈相应的信息,然后服务器终止TCP连接。
现在的HTTP1.1版本都默认Connection:keep-alive 。就是所谓的长连接,在服务器返回客户端信息之后,服务器端不会立刻断开连接,而是保持连接,直到服务器设定Timeout时间限制为止。当然keep-alive 要长期占用服务器的一个TCP 通道,占用服务器的资源。
而对与一些HTTP1.0版本是不识别keep-alive的,所以设置了keep-alive是没有用的。在实际使用中,HTTP头部有了Keep-Alive这个值并不代表一定会使用长连接。
那么如何使服务器和客户端保持长连接,让服务器接受到数据之后就立刻发送给客户端呢?
一,使用ajax长轮询,与服务器保持长连接。
二,使用iframe标签,后台不断输出代码到前端。
三,webSocket方法。
我总结了一下,大体上可以分为上面三类:
1.ajax长轮询:
实际上就是前端,不停连续的发送请求给后端,这样就可以保持前端和后端的连接了。当然,这种暴力的方式也分好和坏。如果你在前端里,写一个while循环,向后端发送ajax请求,那就是这样的情况,前一个请求,后端还没有处理完,另一个请求就发送过来了,请求不断的发送,有很多请求就被搁置,然后阻塞在那里直到自动关闭。这样是最消耗服务器资源的。当然我们可以改善一下:
$.ajax({
url:'mydata',
dataType: 'json',
method:'post',
success:function(data){
//alert(data);
$("#hi").append("姓名:"+data.name+" 性别:"+data.sex);
conn1();
},
error:function(e){
conn1();
}
});
这样的请求就变成,前端发送了请求,直到有数据从后端传送过来,我才继续发送请求。或者我的请求一直在搁置,或者发生错误了,我再发送请求。这样的话就大大减少了前端向后端发送请求的次数,比暴力循环优化了很多。
2.iframe 长连接。
其实iframe标签,可以理解为文档中的文档,就是在html页面中,iframe来执行后端传过来的代码,相当于在html中嵌入一段需要执行的代码。那么利用iframe这个标签,我们可以这样实现长连接。
前端发送一个请求到后端,后端然后开一个循环,不断的向前端的iframe中输出代码,然后iframe执行这段代码,来输出信息。
这里就不想写代码了。
其实这两种方式,前者是让前端死循环,后者是让后端死循环。后端的话,当然可以去开一个线程执行死循环。
3.webSocket
是一种新技术,在客户端和服务器端建立Socket连接,这样前端需要安装flash去执行Socket。这样的方式,前后端可以随心所欲传送数据。网页游戏就是这种方式。
接下来重点介绍Pushlet 框架。
Pushlet框架,百度上说,用了ajax轮询和iframe隐藏帧两种方式实现了服务器推技术。
https://github.com/SilentCC/MyProgramming/blob/master/README.md
我的Git中的WebComet中有源码。下面来看下如何使用。
可以看到目录结构是这样的
我们需要pushlet.jar log4j.properties pushlet.properties sources.properties 和aja-pushlet-client.js 这四个文件,在源代码包里都有。
我们需要再web.xml中配置文件
<servlet>
<servlet-name>pushlet</servlet-name>
<servlet-class>nl.justobjects.pushlet.servlet.Pushlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>pushlet</servlet-name>
<url-pattern>/pushlet.srv</url-pattern>
</servlet-mapping>
然后开始写pushlet的核心类
package com; import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import sun.rmi.runtime.Log;
import nl.justobjects.pushlet.core.Dispatcher;
import nl.justobjects.pushlet.core.Event;
import nl.justobjects.pushlet.core.EventPullSource;
import nl.justobjects.pushlet.*;
import nl.justobjects.pushlet.core.EventSource; public class HelloWorldPushlet implements Serializable{ static public class HwPlushlet extends EventPullSource{ protected long getSleepTime(){ return 3000;
} public Event pullEvent(){ Event event = Event.createDataEvent("/cuige/he");
event.setField("mess", "hello,world!Plushlet!");
//System.out.println("ok");
return event;
} } static public class HsPlushlet implements EventSource{ public void pullEvent(String message){ Event event = Event.createDataEvent("/suige/he");
event.setField("mess", message);
Dispatcher.getInstance().multicast(event);
} public void activate() {
// TODO Auto-generated method stub } public void passivate() {
// TODO Auto-generated method stub } public void stop() {
// TODO Auto-generated method stub } } static public class HsPlushlet2 implements EventSource{ public void pullEvent(String message){ Event event = Event.createDataEvent("/cuige/he");
event.setField("mes", message);
Dispatcher.getInstance().multicast(event);
} public void activate() {
// TODO Auto-generated method stub } public void passivate() {
// TODO Auto-generated method stub } public void stop() {
// TODO Auto-generated method stub } } }
上面这个类是我们自己写的pushlet 的核心类。
在类中,我们有两种方式可以向前端发送信息:
1.继承EventPullSource 类,
在子类中,我们可以设置getSleepTime() 来设置服务器每隔多长时间发送一组数据到前端。
pullEvent是传播数据的方法,在子类中不能有参数
2.实现EventSouce 接口。
pullEvent可以传入参数。实现EventSouce的类,可以在服务器端任何需要的地方去使用~,这样的话我们可以在需要的时候传入需要的参数,然后再发送数据到前端
创建event
Event event = Event.createDataEvent("/cuige/he");
event.setField("mes", message);
广播event
Dispatcher.getInstance().multicast(event);
在前端的话我们可以:
<script type="text/javascript" src="ajax-pushlet-client.js"></script>
<script type="text/javascript"> function conn2(){ PL._init(); PL.joinListen('/suige/he');
alert("ok");
} function onData(event){ alert("ok");
var data =JSON.parse(event.get("mess")); $("#hi2").append("姓名:"+data.name+"性别:"+data.sex); } </script>
PL._init() 是初始化客户端,
PL.joinListen('/suige/he') 是告诉高科端监听哪个event.
function onData(event){} 就是接受数据的函数。
这里我们还要配置数据源,根据我们写的主类,在sources.properties 中设置
source1=com.HelloWorldPushlet$HsPlushlet
source2=com.HelloWorldPushlet$HsPlushlet2
这样的话,我们在一个界面只能监听一个全局的消息。怎么在一个界面的两个地方接受不同的数据源呢?
服务器推技术研究Comet的更多相关文章
- Comet:基于 HTTP 长连接的“服务器推”技术解析
原文链接:http://www.cnblogs.com/deepleo/p/Comet.html 一.背景介绍 传统web请求,是显式的向服务器发送http Request,拿到Response后显示 ...
- Comet:基于 HTTP 长连接的“服务器推”技术
“服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...
- 转载:Comet:基于 HTTP 长连接的“服务器推”技术
转自:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无须客 ...
- [转载] Comet:基于 HTTP 长连接的“服务器推”技术
转载自http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工 ...
- Comet:基于 HTTP 长连接的“服务器推”技术(转载)
“服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信 ...
- 【转】Comet:基于 HTTP 长连接的“服务器推”技术
原文链接:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 很多应用譬如监控.即时通信.即时报价系统都需要将后台发生的变化实时传送到客户端而无 ...
- “服务器推”技术【转载+整理】
原文地址 本文内容 "服务器推(server-push)"技术的应用 基于客户端套接口的"服务器推"技术 基于 HTTP 长连接的"服务器推" ...
- HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)
反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...
- 利用Flash XMLSocket实现”服务器推”技术
利用Flash XML Socket实现”服务器推”技术的基础是:1.Flash提供了XMLSocket类,服务器利用Socket向Flash发送数据:2.JavaScript和Flash的紧密结合, ...
随机推荐
- Android 程序打包及签名(转)
为什么要签名??? 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同样的名字,这时候如何区分?签名这时候就是起区分作用的. 由于开发商可能通过使用相同的Package Name来 ...
- Python中的yield和Generators(生成器)
本文目的 解释yield关键字到底是什么,为什么它是有用的,以及如何来使用它. 协程与子例程 我们调用一个普通的Python函数时,一般是从函数的第一行代码开始执行,结束于return语句.异常或者函 ...
- 【ArcGIS】Web AppBuilder For ArcGIS 配置使用
一.Portal注册 2.Web AppBuilder配置 输入https://XXXX.YYYY.com.cn:3344/webappbuilder/打开配置界面 填写Portal的Url和AppI ...
- centos7 更改主机名
在CentOS或RHEL中,有三种定义的主机名:a.静态的(static),b.瞬态的(transient),以及 c.灵活的(pretty).“静态”主机名也称为内核主机名,是系统在启动时从/etc ...
- 【RF库Collections测试】Keep In Dictionary
Name:Keep In DictionarySource:Collections <test library>Arguments:[ dictionary | *keys ]Keeps ...
- SaltStack Grains 和 Pillar
Grains: (1) grains 是服务器的一系列粒子信息,也就是服务器的一系列物理,软件环境信息(2) grains 是 minion 启动时收集到的一些系统信息,比如操作系统版本.内核版本.C ...
- Jenkins构建触发器
我们在执行Jenkins的项目构建的时候一般都是通过web管理界面中的”构建”来执行项目构建操作,但是除此之外我们还可以通过项目配置中的”构建触发器”来触发构建操作, 其中”构建触发器”有一种方 ...
- Python的Flask框架与数据库连接的教程
命令行方式运行Python脚本 在这个章节中,我们将写一些简单的数据库管理脚本.在此之前让我们来复习一下如何通过命令行方式执行Python脚本. 如果Linux 或者OS X的操作系统,需要有执行脚 ...
- (转载)Java反射机制
Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...
- /etc/profile /etc/profile .bash_profile .bashrc解释
1.用户登录系统时,bash首先执行/etc/profile配置文件和/etc/profile.d/目录下的配置文件,这些配置文件对系统的所有用户都有效,它们设置了普遍性的环境变量. 2.然后,Bas ...