java web 服务器推送技术--comet4j
2018-01-12 16:38
232 查看
java web 服务器推送技术--comet4j
长轮询(lpool)方式,它同样使用的ajax,简单说一下,就是客户端使用ajax发送一个请求,HTTP的连接保持,服务器端会阻塞请求,直到服务器端有一个事件触发或者到达超时。服务器端肯定会开启一个线程,这个线程会时时监测要请求的数据是否有变化,如果有变化,则向客户端输出最新消息,并关闭链接,客户端收到消息处理之后,再次向服务器端请求,如此循环,所以叫长轮询,这种实现方式比起上一种自然要好的多了,不需要客户端不断的ajax请求,减轻服务器端的一定压力,而且可以算得上是实时的。因为这种方案基于
AJAX,请求异步发出,无须安装插件,IE、Mozilla FireFox 都支持。
流方式(长连接 stream),这种和长轮询方式挺像,只有一点区别,就是流方式是在客户端请求服务端并建立链接之后,服务器端始终不会关闭链接(直到超时,断电或者其他特殊情况)每次有数据时,就向客户端进行输出,而不像长轮询每次向客户端输出之后,都要关闭链接。这种方式的另一个优点是可以大大减少发送到服务器的请求,从而避免了与设置服务器连接相关的开销和延时。不幸的是,XMLHttpRequest
在不同的浏览器中有很多不同的实现。这项技术只能在较新版本的 Mozilla Firefox 中可靠地使用。对于 Internet Explorer 或 Safari,仍需使用长轮询。
在长轮询方式下,客户端是在 XMLHttpRequest 的 readystate 为 4(即数据传输结束)时调用回调函数,进行信息处理。当 readystate 为 4 时,数据传输结束,连接已经关闭。Mozilla Firefox
提供了对流方式的支持,即readystate 为 3 时(数据仍在传输中),客户端可以读取数据,从而无须关闭连接,就能读取处理服务器端返回的信息。IE 在 readystate
为 3 时,不能读取服务器返回的数据,目前 IE 不支持流方式(IE11支持)。
当访问含有JS.Engine.start方法(登陆站点成功后的页面都有此方法)页面时:
1.客户端向浏览器发送ajax请求:http://125.220.159.169/WebHr/conn?cmd=conn&cv=0.0.2&ram=0.728455702541396
cmd:客户端连接器动作标识 值有:conn(第一次连接) revival(复活连接) drop(断开连接)
cv:版本号
ram:随机数
2.服务器端进行一系列的处理,会将请求交给第一次连接处理的函数CometEngine.connect()---建立用户连接
(1)将请求封装成CometConnection,在进行一些连接前的事件处理
(2)把要发送的数据封装ConnectionDTO ,并向客户端送数据。若此时连接中断,则将数据放入缓存ConcurrentHashMap<CometConnection, List<CometMessage>>(发送未成功的消息)
发送数据内容:<{"channel":"c4j","data":{"cId":"a58d8c9c-dcf8-40f6-addb-a5729a796226","channels":
["inbox"],"timeout":"60000","ws":"lpool"},"time":"1437050575307"}>
其中cid是用于标记CometConnection连接的。不同窗口cid不一样。
(3)将建立的连接加入ConcurrentHashMap<String, CometConnection> (连接池)其中String:cid
3.客户端收到回复,再次向服务器发送ajax请求http://125.220.159.169/WebHr/conn?cmd=revival&cid=a58d8c9c-dcf8-40f6-addb-a5729a796226&ram=0.5657808198593557
cid即为服务器端生成,标记同一连接的符号。
4.服务器响应函数:CometEngine.revival()连接复活
CometConnection conn = ct.getConnection(cId);根据传过来的cid获取到上次连接的CometConnection对象,将其复活。即是服务器端认为还是第一次的Http连接请求,实现了HTTP长连接。之后向这一连接上发消息,消息来源为cache,也就是ConcurrentHashMap<CometConnection,
List<CometMessage>>里面未发送成功的消息。消息为空则不执行发送操作。
上面代码使用sendToAll方法向所有客户端在"hello"通道上发送了“我来了!”这样一条消息,然后又使用sendTo在同样的通道上向某一个连接发送了“Hi,我是XXX”消息。 CometEngine另外一个很重要的地方在于,它是框架工作的事件引擎的集散地,它提供了BeforeConnectEvent、BeforeDropEvent、ConnectEvent(上线)、DropEvent(下线)、MessageEvent等事件。通过对这些事件的处理来实现具体的功能:
Comet4J配置详解:
长轮询(lpool)方式,它同样使用的ajax,简单说一下,就是客户端使用ajax发送一个请求,HTTP的连接保持,服务器端会阻塞请求,直到服务器端有一个事件触发或者到达超时。服务器端肯定会开启一个线程,这个线程会时时监测要请求的数据是否有变化,如果有变化,则向客户端输出最新消息,并关闭链接,客户端收到消息处理之后,再次向服务器端请求,如此循环,所以叫长轮询,这种实现方式比起上一种自然要好的多了,不需要客户端不断的ajax请求,减轻服务器端的一定压力,而且可以算得上是实时的。因为这种方案基于
AJAX,请求异步发出,无须安装插件,IE、Mozilla FireFox 都支持。
流方式(长连接 stream),这种和长轮询方式挺像,只有一点区别,就是流方式是在客户端请求服务端并建立链接之后,服务器端始终不会关闭链接(直到超时,断电或者其他特殊情况)每次有数据时,就向客户端进行输出,而不像长轮询每次向客户端输出之后,都要关闭链接。这种方式的另一个优点是可以大大减少发送到服务器的请求,从而避免了与设置服务器连接相关的开销和延时。不幸的是,XMLHttpRequest
在不同的浏览器中有很多不同的实现。这项技术只能在较新版本的 Mozilla Firefox 中可靠地使用。对于 Internet Explorer 或 Safari,仍需使用长轮询。
在长轮询方式下,客户端是在 XMLHttpRequest 的 readystate 为 4(即数据传输结束)时调用回调函数,进行信息处理。当 readystate 为 4 时,数据传输结束,连接已经关闭。Mozilla Firefox
提供了对流方式的支持,即readystate 为 3 时(数据仍在传输中),客户端可以读取数据,从而无须关闭连接,就能读取处理服务器端返回的信息。IE 在 readystate
为 3 时,不能读取服务器返回的数据,目前 IE 不支持流方式(IE11支持)。
当访问含有JS.Engine.start方法(登陆站点成功后的页面都有此方法)页面时:
1.客户端向浏览器发送ajax请求:http://125.220.159.169/WebHr/conn?cmd=conn&cv=0.0.2&ram=0.728455702541396
cmd:客户端连接器动作标识 值有:conn(第一次连接) revival(复活连接) drop(断开连接)
cv:版本号
ram:随机数
2.服务器端进行一系列的处理,会将请求交给第一次连接处理的函数CometEngine.connect()---建立用户连接
(1)将请求封装成CometConnection,在进行一些连接前的事件处理
(2)把要发送的数据封装ConnectionDTO ,并向客户端送数据。若此时连接中断,则将数据放入缓存ConcurrentHashMap<CometConnection, List<CometMessage>>(发送未成功的消息)
发送数据内容:<{"channel":"c4j","data":{"cId":"a58d8c9c-dcf8-40f6-addb-a5729a796226","channels":
["inbox"],"timeout":"60000","ws":"lpool"},"time":"1437050575307"}>
其中cid是用于标记CometConnection连接的。不同窗口cid不一样。
(3)将建立的连接加入ConcurrentHashMap<String, CometConnection> (连接池)其中String:cid
3.客户端收到回复,再次向服务器发送ajax请求http://125.220.159.169/WebHr/conn?cmd=revival&cid=a58d8c9c-dcf8-40f6-addb-a5729a796226&ram=0.5657808198593557
cid即为服务器端生成,标记同一连接的符号。
4.服务器响应函数:CometEngine.revival()连接复活
CometConnection conn = ct.getConnection(cId);根据传过来的cid获取到上次连接的CometConnection对象,将其复活。即是服务器端认为还是第一次的Http连接请求,实现了HTTP长连接。之后向这一连接上发消息,消息来源为cache,也就是ConcurrentHashMap<CometConnection,
List<CometMessage>>里面未发送成功的消息。消息为空则不执行发送操作。
Sring channel = "hello"; String someConnectionId = "1125-6634-888"; engine.sendToAll(channel , "我来了!"); engine.sendTo(channel , engine.getConnection(someConnectionId),“Hi,我是XXX”);
上面代码使用sendToAll方法向所有客户端在"hello"通道上发送了“我来了!”这样一条消息,然后又使用sendTo在同样的通道上向某一个连接发送了“Hi,我是XXX”消息。 CometEngine另外一个很重要的地方在于,它是框架工作的事件引擎的集散地,它提供了BeforeConnectEvent、BeforeDropEvent、ConnectEvent(上线)、DropEvent(下线)、MessageEvent等事件。通过对这些事件的处理来实现具体的功能:
public class CommetInit implements ServletContextListener { /** * 初始化 */ public void contextInitialized(ServletContextEvent arg0) { CometContext cc = CometContext.getInstance(); cc.registChannel(Contants.APP_CHANNEL);// 注册通道 CometEngine engine = cc.getEngine(); // 绑定上线事件侦听 engine.addListener(ConnectEvent.class, new LoginListenner()); // 绑定下线事件侦听 engine.addListener(DropEvent.class, new LogOutListener()); } public void contextDestroyed(ServletContextEvent arg0) { // TODO 该方法尚未实现 } } public class LoginListenner extends ConnectListener { @Override public boolean handleEvent(ConnectEvent anEvent) { CometConnection conn = anEvent.getConn(); CometEngine engine = CometContext.getInstance().getEngine(); CometContext.getInstance().getEngine().sendTo("hello", engine.getConnection(conn.getId()),"欢迎上线"); return true; } } public class LogOutListener extends DropListener { @Override public boolean handleEvent(DropEvent anEvent) { CometConnection conn = anEvent.getConn(); if (conn != null) { String id = conn.getId(); removeData(id); destoryThread(id); } return true; } }
Comet4J配置详解:
<!--Comet4J配置最简配置 --> <listener> <description>Comet4J容器侦听</description> <listener-class>org.comet4j.core.CometAppListener</listener-class> </listener> <servlet> <display-name>CometServlet</display-name> <servlet-name>CometServlet</servlet-name> <servlet-class>org.comet4j.core.CometServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CometServlet</servlet-name> <url-pattern>/comet</url-pattern> </servlet-mapping>
<!--comet4j应用配置--> <listener> <listener-class>com.fiberhome.smartas.fitoa.wflow.inner.util.CommetInit</listener-class> </listener> <servlet> <description>获取待办提醒</description> <display-name>reminder</display-name> <servlet-name>reminder</servlet-name> <servlet-class>com.fiberhome.smartas.fitoa.wflow.inner.util.ReminderUtil</servlet-class> </servlet> <servlet-mapping> <servlet-name>reminder</servlet-name> <url-pattern>/reminder</url-pattern> </servlet-mapping>
<!--Comet4J详细配置 --> <listener> <description>Comet4J容器侦听</description> <listener-class>org.comet4j.core.CometAppListener</listener-class> </listener> <servlet> <description>Comet连接[默认:org.comet4j.core.CometServlet]</description> <display-name>CometServlet</display-name> <servlet-name>CometServlet</servlet-name> <servlet-class>org.comet4j.core.CometServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CometServlet</servlet-name> <url-pattern>/conn</url-pattern> </servlet-mapping>
<!-- Comet4J可选参数配置--> <context-param> <description>语言[支持:zh,en,默认:zh,详细http://www.loc.gov/standards/iso639-2/php/English_list.php]</description> <param-name>Comet.Language</param-name> <param-value>zh</param-value> </context-param> <context-param> <description>请求超时时间/微妙[默认:60000,1分钟,建议至少设置3秒以上]</description> <param-name>Comet.Timeout</param-name> <param-value>60000</param-value> </context-param> <context-param> <description>连接空闲过期时间/微妙[默认:5000,5秒]</description> <param-name>Comet.ConnExpires</param-name> <param-value>5000</param-value> </context-param> <context-param> <description>连接检查频率/微妙[默认:5000,5秒]</description> <param-name>Comet.ConnFrequency</param-name> <param-value>5000</param-value> </context-param> <context-param> <description>缓存信息过期时间/微妙[默认:60000,1分种]</description> <param-name>Comet.CacheExpires</param-name> <param-value>60000</param-value> </context-param> <context-param> <description>缓存信息过期检查频率/微妙[默认:60000,1分种]</description> <param-name>Comet.CacheFrequency</param-name> <param-value>60000</param-value> </context-param> <context-param> <description>连接模式[auto(默认)/stream/lpool]</description> <param-name>Comet.WorkStyle</param-name> <param-value>auto</param-value> </context-param> <context-param> <description>开启调试[false(默认)/true]</description> <param-name>Comet.Debug</param-name> <param-value>false</param-value> </context-param>
相关文章推荐
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- java web 服务器推送技术--comet4j
- PHP Web实时消息后台服务器推送技术--GoEasy
- Java中使用Comet4j实现服务器推送实现时报错
- 服务器推送技术
- Android 服务器推送技术
- Android 服务器推送技术
- HTML服务器推送技术简介
- Comet, 下一代反向AJAX(即服务器推送技术- Server-side push)
- Android 服务器推送技术