转自:

http://blog.chenzuhuang.com/archive/28.html

http://www.cnblogs.com/xdp-gacl/p/5193279.html

一.WebSocket简单介绍

  随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

  我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。在WebSocket规范提出之前,开发人员若要实现这些实时性较强的功能,经常会使用折衷的解决方法:轮询(polling)Comet技术。其实后者本质上也是一种轮询,只不过有所改进。

  轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。

  Comet技术又可以分为长轮询流技术长轮询改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。流技术通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。

  这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。

  伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。

  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以上的版本才能运行。

二.WebSocket示例

2.1.新建JavaWeb测试项目

  

  在pom.xml中添加Jar包依赖

1 <dependency>
2         <groupId>javax</groupId>
3         <artifactId>javaee-api</artifactId>
4         <version>7.0</version>
5         <scope>provided</scope>
6 </dependency>

  客户端(Web主页)代码:

 1 <%@ page language="java" pageEncoding="UTF-8" %>
 2 <!DOCTYPE html>
 3 <html>
 4 <head>
 5     <title>Java后端WebSocket的Tomcat实现</title>
 6 </head>
 7 <body>
 8     Welcome<br/><input id="text" type="text"/>
 9     <button onclick="send()">发送消息</button>
10     <hr/>
11     <button onclick="closeWebSocket()">关闭WebSocket连接</button>
12     <hr/>
13     <div id="message"></div>
14 </body>
15
16 <script type="text/javascript">
17     var websocket = null;
18     //判断当前浏览器是否支持WebSocket
19     if ('WebSocket' in window) {
20         websocket = new WebSocket("ws://localhost:8080/websocket");
21     }
22     else {
23         alert('当前浏览器 Not support websocket')
24     }
25
26     //连接发生错误的回调方法
27     websocket.onerror = function () {
28         setMessageInnerHTML("WebSocket连接发生错误");
29     };
30
31     //连接成功建立的回调方法
32     websocket.onopen = function () {
33         setMessageInnerHTML("WebSocket连接成功");
34     }
35
36     //接收到消息的回调方法
37     websocket.onmessage = function (event) {
38         setMessageInnerHTML(event.data);
39     }
40
41     //连接关闭的回调方法
42     websocket.onclose = function () {
43         setMessageInnerHTML("WebSocket连接关闭");
44     }
45
46     //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
47     window.onbeforeunload = function () {
48         closeWebSocket();
49     }
50
51     //将消息显示在网页上
52     function setMessageInnerHTML(innerHTML) {
53         document.getElementById('message').innerHTML += innerHTML + '<br/>';
54     }
55
56     //关闭WebSocket连接
57     function closeWebSocket() {
58         websocket.close();
59     }
60
61     //发送消息
62     function send() {
63         var message = document.getElementById('text').value;
64         websocket.send(message);
65     }
66 </script>
67 </html>

  Java Web后端代码

 1 package me.gacl.websocket;
 2
 3 import java.io.IOException;
 4 import java.util.concurrent.CopyOnWriteArraySet;
 5
 6 import javax.websocket.*;
 7 import javax.websocket.server.ServerEndpoint;
 8
 9 /**
10  * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
11  * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
12  */
13 @ServerEndpoint("/websocket")
14 public class WebSocketTest {
15     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
16     private static int onlineCount = 0;
17
18     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
19     private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
20
21     //与某个客户端的连接会话,需要通过它来给客户端发送数据
22     private Session session;
23
24     /**
25      * 连接建立成功调用的方法
26      * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
27      */
28     @OnOpen
29     public void onOpen(Session session){
30         this.session = session;
31         webSocketSet.add(this);     //加入set中
32         addOnlineCount();           //在线数加1
33         System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
34     }
35
36     /**
37      * 连接关闭调用的方法
38      */
39     @OnClose
40     public void onClose(){
41         webSocketSet.remove(this);  //从set中删除
42         subOnlineCount();           //在线数减1
43         System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
44     }
45
46     /**
47      * 收到客户端消息后调用的方法
48      * @param message 客户端发送过来的消息
49      * @param session 可选的参数
50      */
51     @OnMessage
52     public void onMessage(String message, Session session) {
53         System.out.println("来自客户端的消息:" + message);
54         //群发消息
55         for(WebSocketTest item: webSocketSet){
56             try {
57                 item.sendMessage(message);
58             } catch (IOException e) {
59                 e.printStackTrace();
60                 continue;
61             }
62         }
63     }
64
65     /**
66      * 发生错误时调用
67      * @param session
68      * @param error
69      */
70     @OnError
71     public void onError(Session session, Throwable error){
72         System.out.println("发生错误");
73         error.printStackTrace();
74     }
75
76     /**
77      * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
78      * @param message
79      * @throws IOException
80      */
81     public void sendMessage(String message) throws IOException{
82         this.session.getBasicRemote().sendText(message);
83         //this.session.getAsyncRemote().sendText(message);
84     }
85
86     public static synchronized int getOnlineCount() {
87         return onlineCount;
88     }
89
90     public static synchronized void addOnlineCount() {
91         WebSocketTest.onlineCount++;
92     }
93
94     public static synchronized void subOnlineCount() {
95         WebSocketTest.onlineCount--;
96     }
97 }

1.2.运行效果

  同时打开Google浏览器和火狐浏览器进行多客户端模拟测试,运行效果如下:

  

  该Demo在Jdk1.7+Tomcat7.0.65下环境测试过,示例项目代码下载

  

Java后端WebSocket的Tomcat实现相关推荐

  1. Java后端WebSocket的Tomcat实现(转载)

    一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通 ...

  2. websocket java 测试_Java后端WebSocket的Tomcat实现

    1 package me.gacl.websocket; 2 3 import java.io.IOException; 4 import java.util.concurrent.CopyOnWri ...

  3. Java后端WebSocket的实现

    WebSocket 1.什么是WebSocket? webSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议. webSocket使得客户端和服务器之间的数据交换变得更加简单 ...

  4. java ws协议_基于java实现websocket协议过程详解

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...

  5. java使用websocket前后端通信实现

    文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源. WebSocket是客户端和服务器端的一个通信,WebSocket分为客户端和服务端,所以我 ...

  6. 学习java后端第一步-安装TOMCAT

    1.安装tmocat,可以直接去官网下载.下载网址:http://tomcat.apache.org/download-80.cgi#8.5.5 下载可直接安装的,不停的点下一步即可 2.配置环境 流 ...

  7. java项目如何启动tomcat服务器,Java web项目启动Tomcat报错解决方案

    Java web项目启动Tomcat报错解决方案 点击运行项目时显示 A Java Exception has occurred. 'Starting Tomcat v9.0 Server at lo ...

  8. java后端面试大全,java后端面试宝典

    文章目录 -2 flink -1 linux of view linux查看占用cup最高的10个进程的命令: 〇.分布式锁 & 分布式事务 0-1分布式锁--包含CAP理论模型 概述 分布式 ...

  9. [java手把手教程][第二季]java后端博客系统文章系统——No10

    项目github地址:github.com/pc859107393- 实时项目同步的地址是国内的码云:git.oschina.net/859107393/m- 我的简书首页是:www.jianshu. ...

最新文章

  1. html5圆形图片轮播,jQuery超酷响应式圆形图片轮播图特效
  2. 推荐7款超良心的windows软件,每一个都是精品!
  3. weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB cannot be cast to oracle.sql.BLOB 解决方法
  4. 【ArcGIS 10.2新特性】Geodatabase 10.2 常见问题
  5. django连接redis 集群(安装redis的相关包的时候亲测)
  6. 寻找性能更优秀的不可变小字典
  7. 使用JavaParser从源文件中提取JavaDoc文档
  8. react优秀项目案例_关于进行2019年北京市高等学校“实培计划”项目——毕业设计(创业类)项目总结与优秀项目案例征集的通知...
  9. vue 开发依赖安装
  10. MATLAB Tick的方向(刻度标外翻)
  11. Java PC端微信、支付宝扫码支付(一)
  12. 如何批量识别二维码图片信息?
  13. 注册表看计算机配置命令行,regedit-注册表编辑器及其命令行使用
  14. 【Python实用工具】暴力破解-2!Python编写八位数密码本
  15. 大数据:阿里数据仓库建模及管理体系OneData什么是阿里onedata
  16. selectpicker的使用方法
  17. ffmpeg生成hls点播
  18. 100天成就卓越领导力:新晋领导者的First100训练法
  19. mysql的设置参数中max_allowed_packet
  20. 学习感悟-如何养成良好的编程习惯

热门文章

  1. Linux下docker安装配置oracle,oracle创建用户并远程连接,实测可用!
  2. 2022-2028年中国饮水机市场投资分析及前景预测报告
  3. 2022-2028年中国气相防锈薄膜行业市场发展调研及投资前景分析报告
  4. Python+OpenCV 图像处理系列(7)—— 图像色彩空间及转换
  5. 发送快递:配置静态路由
  6. 批量梯度下降(BGD)、随机梯度下降(SGD)以及小批量梯度下降(MBGD)的理解
  7. 一起读Bert文本分类代码 (pytorch篇 五)
  8. LeetCode简单题之二叉搜索树中的搜索
  9. Node.js 简单入门
  10. 自动驾驶系统关系与自动泊车原理