一、comet简介:

comet :基于 HTTP长连接的“服务器推”技术,是一种新的 Web 应用架构。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。

二、comet4j功能特性

  • 推送消息广播。
  • 推送定向消息。
  • 提供连接上线前、上线、下线前、下线、发送消息等多种可处理事件。
  • 消息缓存机制,确保长轮询工作模式下不丢失消息。
  • 客户端正常下线,服务端可立即感知。
  • 客户端异常停止工作,服务端可定时检查并感知。
  • 以注册通道应用的方式,让开发者对框架功能进行扩展,实现自己的应用。

三、comet4j框架特性

  • 独立小巧,不依赖于第三方包。
  • 与应用紧密集成,无需独立应用或服务器。
  • 与Session无关的连接机制,为开发人员提供最大程度的功能可控性。
  • 面向事件编程,客户端与服务器端均为事件驱动开发模式,提供了良好的可扩展性机制。
  • 各项性能参数均可配置。
  • 支持多种主流浏览器,并支持Air应用环境。

四、comet4j实战应用

  (1)下载comet4j所需要的jar包和js文件。具体下载地址:http://code.google.com/p/comet4j/

  (2)新建web项目:如图 项目demo下载地址:http://pan.baidu.com/s/1hqsUpzI

    

   (3)在demo中可以发现,index.jsp中所用的CHANNEL必须与Comet4j.java中设置的CHANNEL相一致,在整个推送中,

     采用的是单例模式,所以开发人员不必担心它会消耗大量的内存。

   (4)comet4j开发简单,只需参考其客户端和服务端的API文档,做出你想要的推送功能应该是没有问题的。

  第二种:大家比较熟悉

一.WebSocket简单介绍
一.WebSocket简单介绍
  随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。$ j6 s6 P/ d( K- G' m
  我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。在WebSocket规范提出之前,开发人员若要实现这些实时性较强的功能,经常会使用折衷的解决方法:轮询(polling)和Comet技术。其实后者本质上也是一种轮询,只不过有所改进。
  轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。
  Comet技术又可以分为长轮询和流技术。长轮询改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。流技术通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。
  这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。. C  w( i) E4 k. P, m; g
  伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过javaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。# k- L0 {# i. k
  JavaEE 7中出了JSR-356:Java API for WebSocket规范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat从7.0.27开始支持 WebSocket,从7.0.47开始支持JSR-356,下面的Demo代码也是需要部署在Tomcat7.0.47以上的版本才能运行。# W" f) D, @: u) Y0 L' ~

二、WebSocket协议介绍
 WebSocket协议是一种双向通信协议,它建立在TCP之上,同http一样通过TCP来传输数据,但是它和http最大的不同有两点:1.WebSocket是一种双向通信协议,在建立连接后,WebSocket服务器和Browser/UA都能主动的向对方发送或接收数据,就像Socket一样,不同的是WebSocket是一种建立在Web基础上的一种简单模拟Socket的协议;2.WebSocket需要通过握手连接,类似于TCP它也需要客户端和服务器端进行握手连接,连接成功后才能相互通信。简单的建立握手的时序图如下:+ h; ~; q4 `/ {
<ignore_js_op> 
握手过程:
Browser与WebSocket服务器通过TCP三次握手建立连接,如果这个建立连接失败,那么后面的过程就不会执行,Web应用程序将收到错误消息通知。
在TCP建立连接成功后,Browser/UA通过http协议传送WebSocket支持的版本号,协议的字版本号,原始地址,主机地址等等一些列字段给服务器端。
WebSocket服务器收到Browser/UA发送来的握手请求后,如果数据包数据和格式正确,客户端和服务器端的协议版本号匹配等等,就接受本次握手连接,并给出相应的数据回复,同样回复的数据包也是采用http协议传输。- s" j: [- c" o- k
Browser收到服务器回复的数据包后,如果数据包内容、格式都没有问题的话,就表示本次连接成功,触发onopen消息,此时Web开发者就可以在此时通过send接口想服务器发送数据。否则,握手连接失败,Web应用程序会收到onerror消息,并且能知道连接失败的原因。5 V, k5 ?2 l7 M( \2 b  H
' z7 g9 w, D$ O% k) U
三、Tomcat 7中的Websocket架构3 E7 s, g+ f% r% u4 Y% `
) F' S5 |4 q- W
如图所示,因为Websocket通信分为握手和数据传输两个过程,两个过程中需要用到的处理方式是不一样的,握手过程是基于HTTP 1.1基础上的,而数据传输是直接基于TCP的流传输。 ' ]4 R- C. L! S5 x; y* j
       握手过程中,在HttpServletRequest的基础上,封装了WsHttpServletRequest类,添加了对Request的失效操作函数invalidate()。而在数据通信时,接受和处理数据过程中,基于org.apache.coyote.http11.upgrade.UpgradeInbound重新封装了用于处理数据输入流的类StreamInbound,并在StreamInbound的基础上扩展生成了用于消息处理的类MessageInbound。在这两个数据处理类中均留有onData,onTextData/onBinaryData,onOpen,onClose等事件操作函数接口,这些接口将在载入的代码类中实现业务逻辑。在用于数据输出流的类WsOutbound则是封装了UpgradeOutbound对象实例,基于UpgradeOutbound对象的基础上,添加了websocket响应有关的处理逻辑。这里处理函数均为同步调用的函数,保证websocket响应的时序性。
       Tomcat中Websocket的处理流程如下:<ignore_js_op> 
接收客户端发来的握手请求,Coyote.http11连接器对socket进行解析,形成HttpServletRequest发送给Container。
Container中的相应WebsocketServlet处理请求,如不接受连接请求,则返回,如接受连接请求,则对请求作出响应,建立起客户端和服务器的socket连接。
服务器此时可以通过WsOutbound发送数据给客户端,同时通过StreamInbound监听socket。/ d3 C$ S' N4 s" m
如果接收到客户端发来的数据,则将socket数据解析成frame,判断frame类型,通过事件分发数据到不同的逻辑处理流程。
数据返回时调用WsOutbound对返回的数据进行封装处理,发送给客户端。

四、代码实现以及需求

1、项目需要,定时向所有在线用户推送一个广告或是推送一个通知之类的(比如服务器升级,请保存好手头工作之类的)。: f  |, D6 R. _0 ~3 d
' p- `, F0 Y* g4 B. g9 ]# `
2、相关环境 , Nginx、tomcat7、centos 6.5
7 }  m0 R% \$ F' u1 A
3、项目框架,springMvc 4.0.6、layer
! u- Q0 {: B2 u- e. `6 G
4、代码实现:) W  R/ N6 U/ C& L/ t3 R) a& h

WebSocketConfig:

  1. import websocket.handler.SystemWebSocketHandler;$ `, D+ H. H9 E  J7 R
  2. @Configuration
  3. @EnableWebMvc
  4. @EnableWebSocket9 Z9 l6 i" h) g4 G$ S" ^& Q
  5. public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{6 K% ]3 U1 O# C- {% n
  6. @Override+ J+ `% d% m  |3 j6 I7 A+ u' \
  7. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
  8. registry.addHandler(systemWebSocketHandler(),"/webSocketServer");4 H0 k% Y9 o8 `/ L6 y7 W/ B' n
  9. registry.addHandler(systemWebSocketHandler(),"/sockjs/webSocketServer");
  10. }
  11. @Bean' \6 ], m4 }% f' E' U" \
  12. public WebSocketHandler systemWebSocketHandler(){
  13. return new SystemWebSocketHandler();: S- |& U# }/ C" G$ v5 a
  14. }
  15. }

复制代码

SystemWebSocketHandler:

  1. public class SystemWebSocketHandler extends  TextWebSocketHandler {
  2. % }- u" Q6 D# F# P# w; P2 d
  3. private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();;4 ?+ A. V$ Y/ }& h
  4. x- y) r8 U/ n; M+ Y$ l
  5. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  6. System.out.println("ConnectionEstablished");
  7. users.add(session);% X7 y- v( \* u! ^
  8. System.out.println("当前用户"+users.size());
  9. }! k5 d' v$ [3 b, u5 l, z
  10. /**( b# S3 }0 }* ?; x* ^
  11. * 在UI在用js调用websocket.send()时候,会调用该方法
  12. * @Author    张志朋7 f& A# K4 g8 X. z- |) S3 K
  13. * @param session
  14. * @param message- n) Q; i2 ?5 Y, d4 m
  15. * @throws Exception
  16. * @Date    2016年3月4日
  17. * 更新日志& n. c% Q; Y# ]
  18. * 2016年3月4日 张志朋  首次创建
  19. *
  20. */
  21. @Override
  22. protected void handleTextMessage(WebSocketSession session,5 l. }, a5 j4 W8 j, U% x
  23. TextMessage message) throws Exception {( ~( P! W; T. H$ G* U8 W
  24. super.handleTextMessage(session, message);
  25. sendMessageToUsers(session,message);
  26. }
  27. @Override9 m3 d( B# t% r" z0 e
  28. public void handleTransportError(WebSocketSession session, Throwable exception) throws IOException {
  29. if(session.isOpen()){% x  j0 I! c0 S5 Y
  30. session.close();
  31. }
  32. users.remove(session);5 @6 y! F$ k, D- s/ N9 v5 V
  33. }) m1 |, z8 r$ ]0 B
  34. @Override
  35. public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {& u* X6 C/ N* }. ?. e2 w
  36. users.remove(session);, o, ?0 A. J7 o2 z6 `' b
  37. }8 p# X, ?0 m7 `+ J
  38. % V3 r% E, m; }1 ]5 D
  39. @Override) A1 [; K/ }6 D% [! ^
  40. public boolean supportsPartialMessages() {& Y' N& U! ~* z( m! h* {. f
  41. return false;
  42. }  t9 ]* K% z7 C( C# E- |- F+ i
  43. /**! Z3 L$ S' Q. \1 G- p: I3 {. D1 E9 W
  44. * 给所有在线用户发送消息
  45. * @Author    张志朋
  46. * @param message  void* Y) `$ f0 T4 M+ b6 q8 X2 p5 F
  47. * @Date    2016年3月4日
  48. * 更新日志1 q% I4 Y  E. @. Z# H- E
  49. * 2016年3月4日 张志朋  首次创建
  50. *5 V5 u3 a+ G5 r# P+ f, Y/ {
  51. */2 H6 z3 A/ m4 ?0 h( ~5 o% X
  52. public void sendMessageToUsers(WebSocketSession session,TextMessage message) {/ l  f: d! @" [% g% ]% j! ?
  53. for (WebSocketSession user : users) {
  54. try {; K! [3 k) B! }. v
  55. if (user.isOpen()) {
  56. user.sendMessage(message);, ?$ r7 A% ?  n1 ]. [7 @$ j
  57. }
  58. } catch (IOException e) {
  59. e.printStackTrace();: c1 t* |1 j$ I% o4 t8 H
  60. }% ]6 X6 _9 e) z, `) j% `! H2 N
  61. }
  62. }2 ^# o( i  `( h' Z7 L
  63. }

复制代码

信息输入 index.html:- \0 z& k; w5 d$ U1 ~( ~* T

  1. <html xmlns="http://www.w3.org/1999/xhtml">
  2. <head>7 a8 f3 O5 v; b# g3 B: ^
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  4. <title>请输入任意消息</title>
  5. <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>7 @( l1 e# @) X
  6. <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
  7. <script type="text/javascript">
  8. var ws = null;
  9. $(function () {
  10. if ('WebSocket' in window) {
  11. ws = new WebSocket('ws://127.0.0.1:8080/webSocketServer'); 5 S+ j  {# E8 F2 o( ^2 L8 A: f: F" d
  12. }
  13. else if ('MozWebSocket' in window) {$ j1 }4 R% _- _& z3 F
  14. ws = new MozWebSocket("ws://127.0.0.1:8080/webSocketServer");
  15. }
  16. else {
  17. ws = new SockJS("ws://127.0.0.1:8080/webSocketServer");+ P& w: ?* O' _/ [6 e' t, {0 F
  18. }. v- m! b& `; f0 P3 C5 t
  19. ws.onopen = function () {/ B$ e  Q$ b) D
  20. / K$ l6 b6 S7 m2 j' A; m/ j
  21. };
  22. ws.onmessage = function (event) {3 O! h. f! h$ m7 Q* M: s2 Y
  23. " V1 p. q# `/ K
  24. };
  25. ws.onclose = function (event) {
  26. 6 D7 _" h$ ?, Y
  27. };! e8 }; o, ^! }( o, Q2 r6 \+ z. o( M
  28. });
  29. function stop(){+ x8 U6 s7 p. c( U; G0 i
  30. var message = $("#message").val();$ w. u: E" p5 `! I
  31. ws.send(message);6 G  u8 P3 a( O  |5 W8 g8 [
  32. }
  33. </script>; u% \/ M8 b7 O0 D5 t5 h" _
  34. </head>9 U  H/ y, ^' M- f# N
  35. <body class="keBody">  X0 D& H9 u5 d( e0 C: F/ `: R) Q
  36. 请输入提示信息: <textarea id="message"></textarea><br />
  37. <input type="button"  value="开始" />
  38. </body>5 ?% i; h6 ?2 b4 M. [/ f/ b+ j
  39. </html>

复制代码

6 q0 F$ y& l  t8 y" a( U( I& n
webSocket.js  用于导入项目。

  1. document.write("<script language=javascript src='http://127.0.0.1:8080/js/jquery-1.10.2.min.js'></script>");
  2. document.write("<script language=javascript src='http://127.0.0.1:8080/layer/layer.js'></script>");; Z" F* y3 X" ^* A6 {! Q9 @( M
  3. document.write("<script language=javascript src='http://cdn.sockjs.org/sockjs-0.3.min.js'></script>");
  4. var ws = null;0 K' _) I, _( z: |( t$ b. g
  5. var basePath = "ws://127.0.0.1:8080/";9 i2 {9 p1 H' T9 b' U
  6. if ('WebSocket' in window) {# w8 N+ p" v, F/ v% K
  7. ws = new WebSocket(basePath+'webSocketServer'); 4 q. Z! u% i( I' }. t) o1 |
  8. }
  9. else if ('MozWebSocket' in window) {
  10. ws = new MozWebSocket(basePath+"webSocketServer");0 }9 y3 Y9 T% m3 ?/ [; b; Y7 p
  11. }
  12. else {, p. l% Z1 e6 t/ D. m8 q
  13. ws = new SockJS(basePath+"sockjs/webSocketServer");
  14. }" C8 y7 f/ C. }# [& W# G
  15. ws.onopen = function () {
  16. + J/ T- r4 L" d) [' b9 L2 T
  17. };3 R6 @8 v! b1 K# O
  18. ws.onmessage = function (event) {
  19. pop(event.data);- C6 d! {5 ^1 q5 a
  20. };
  21. ws.onclose = function (event) {
  22. ws.close();1 \8 x$ [- o2 \/ Z
  23. };
  24. //提示信息
  25. function pop(message){. ]  Q% }1 `; B
  26. layer.alert(message);* d4 H2 b0 }) I( j, ~, k
  27. }

复制代码

9 \; ^. D: M; Y% o5 B2 [
5、在项目头部引入% D0 _; w8 y) {( C: n6 e$ K
<script language=javascript src='http://127.0.0.1:8080/webSocket.js '></script>

这时查看后台 会有以下信息 说明 引入成功。# T; \, y% L  c+ d1 ~% U
<ignore_js_op>

然后在打开页面 index.html 输入以下内容 点击开始即可。/ d% h3 B% d: \9 E
<ignore_js_op>

如果在网站出现一下提示说明配置成功,这时候所有网站登录用户都可以收到此信息。, N5 ^, y) H4 C2 ]3 c* }
<ignore_js_op>

转载于:https://www.cnblogs.com/huojg-21442/p/7090683.html

WEB消息推送-comet4j相关推荐

  1. WEB消息推送—GoEasy

    web实时推送的技术在大多数项目里面都会用到,尤其是一些实时性要求高的项目,关于这方面的实现技术有许多,类似于webscoket.dwr.comet4j和netpush等等,其中在以往的篇幅里我也介绍 ...

  2. SSE(Server-sent Events)实现Web消息推送(SpringBoot)

    本文参考自: Web消息推送之SSE_魅Lemon的博客-CSDN博客_sse推送 [IT老齐237]超好用Web服务端主动推送技术SSE_哔哩哔哩_bilibili 1.Web消息推送简介 短轮询 ...

  3. php实现Web消息推送框架

    文章来源:http://www.workerman.net/web-sender web-msg-sender是一款web长连接推送框架,采用PHPSocket.IO开发,基于WebSocket长连接 ...

  4. php socket laravel,Laravel整合PHPSocket.Io实现web消息推送

    PHPSocket.IO ,PHP跨平台实时通讯框架 PHPSocket.IO是 PHP 版本的Socket.IO服务端实现,基于workerman开发,用于替换node.js版本Socket.IO服 ...

  5. SSM项目使用GoEasy 实现web消息推送服务

      一.背景 之前项目需要做一个推送功能,最开始我用websocket实现我的功能.使用websocket的好处是免费自主开发,但是有几个问题:1)浏览器的兼容问题,尤其是低版本的ie:2)因为是推送 ...

  6. Web消息推送之SSE

    文章目录 一.消息推送简介 1.消息推送介绍 2.几种方式介绍 二.SSE原理介绍 1.SSE基础概念 2.SSE特点 3.SSE与WebSocket异同 三.SSE推送实现 1.概述 1.1 使用S ...

  7. 基于workerman实现的web消息推送站内信功能

    流程说明 使用 web-msg-sender 作为 服务器监听程序. 客户端(浏览器)通过websocket连接 服务器监听程序. 服务器应用程序(后端) 通过curl访问 服务器监听程序,将需要推送 ...

  8. 关于 Web消息推送系统 web-msg-sender 配置https 协议

    前几天做了一个语音播报功能,本地测试ok,但是上线要求https协议费了点时间 1.启动失败情况出现如下错误 Waring stream_socket_server has been disabled ...

  9. Web 实时消息推送详解

    title: Web 实时消息推送详解 category: 系统设计 head: meta name: keywords content: 消息推送,短轮询,长轮询,SSE,Websocket,MQT ...

最新文章

  1. 知名文件传输协议 SCP 被曝存在 35 年历史的安全漏洞
  2. 二手轻型载货车报价图片_别买贵了,老陈带你走进二手iPhone的大本营:深圳飞扬市场...
  3. 2021 icme_重磅 | 2021年U.S. News 全美院校排名发布,疫情之下,排名大洗牌?!
  4. pytorch 正向与反向传播的过程 获取模型的梯度(gradient),并绘制梯度的直方图
  5. aliyun centos6 安装mysql_阿里云CentOS6.8安装MySQL5.6
  6. Go语言基础之4--流程控制
  7. filco蓝牙不好用_「原创」开箱 FILCO 斐尔可 蓝牙双模键盘+更换键帽
  8. centos 7 vs centos6 的不同
  9. 程序员降薪求职到底该不该?
  10. 添加鼠标右键菜单项(EditPlus为例)
  11. Presentation Prompter for Mac(屏幕提词器)
  12. “英伦配”收视牛过本山,网管软件如何配奇兵
  13. Mysql(8)_存储引擎之InnoDB
  14. 什么是多线程,锁,死锁,怎么避免死锁(转)
  15. 手写笔记软件评测Notability、GoodNotes、MarginNote、OneNote
  16. uniapp-登录界面风格-001
  17. gcc/g++编译错误Assembler Error
  18. Spyder窗口布局调整
  19. 知乎 | 大家都见过哪些让你虎躯一震的代码?
  20. 蓄水池采样算法的python实现_蓄水池采样算法-Reservoir Sampling

热门文章

  1. 企业上市上市央企大面积亏损折射出啥弊端?
  2. myeclipse 8.5 安装jbpm3.2开发插件
  3. SYN攻击原理以及检测防范技术
  4. Mr.J---重拾Ajax(一)--XMLHttpRequest
  5. Devexpress Chart series 点击时获取SeriesPoint的值
  6. java笔记--重定向输出流实现程序输出到日志
  7. JavaScript表单序列化的方法详解
  8. NSArray与NSSet的区别
  9. hdu 2188巴什博弈
  10. Python异常:TypeError: a bytes-like object is required, not 'str'