WebSocket实时异步通信

WebSocket实时异步通信

【一】WebSocket简介

  WebSocket是HTML5推出一个协议规范,用来B/S模式中服务器端和客户端之间进行实时异步通信。

  众所周知,传统的HTTP协议中,服务器端和客户端通信只能是在客户端发送一个请求之后,服务器端才能对其响应,也就是说服务器端是不能够主动向客户端发起数据的。

  当在服务器端和客户端之间需要频繁地实时通信时,传统HTTP协议只能通过Ajax轮询的方式,即客户端每隔一段时间请求一次服务器来获得更新,这样做的对服务器的性能要求特别高,而且占用很多无用的带宽、流量。

 

 

图一 传统HTTP请求会话

图二 WebSocket请求会话

  WebSocket在实时通信方面很好的弥补了传统HTTP协议的不足。它是一个建立在HTTP协议之上的协议,通过HTTP建立了WebSocket连接之后,服务器端和客户端就可以随时通信了。

 

【二】WebSocket的使用

服务器端

  Tomcat7.0.5版本及以后的版本之中已经内嵌了支持WebSocket标准协议的jar包websocket-api.jar;在服务器端开发中通过@ServerEndpoint注解表明WebSocket服务端运行在 ws://[Server端IP或域名]:[Server端口]/project-name/注解参数值 路径指定的位置,客户端在创建WebSocket对象的时候,通过该路径指定服务器响应的WebSocket。

  @OnOpen@OnClose、@OnError注解WebSocket方法分别响应建立连接、关闭连接和出错时候的回调函数,@OnMessage注解的方法响应收到客户端发送数据的回调函数。Session相当于客户端,可以向客户端发送数据。

  WebSocket类处理客户端的所有请求,然后根据不同页面的请求调用不同的类对象进行处理。

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.websocket.Session;
import org.apache.log4j.Logger;
import net.sf.json.JSONObject;

@ServerEndpoint("/websocket") public class WebSocket {public static Logger log = Logger.getLogger(WebSocket.class); private Statement stmt = null;private Connection conn = null; private Timer timer;@OnOpenpublic void onOpen(Session s) { log.info("client connected");timer = new Timer();//connect databasetry {ResourceBundle config = ResourceBundle.getBundle("config");String driver = config.getString("jdbc.driver");String url = config.getString("jdbc.cfg.url");String username = config.getString("jdbc.cfg.username");String password = config.getString("jdbc.cfg.password");Class.forName(driver);conn = DriverManager.getConnection(url, username, password);stmt = conn.createStatement(); log.info("connect database successful");}catch (ClassNotFoundException e) {e.printStackTrace();}catch (SQLException e) {e.printStackTrace();}}@OnMessagepublic void onMessage(final String message, Session s) throws IOException, InterruptedException{log.info("message="+message);final JSONObject json = JSONObject.fromString(message);if(json.getInt("pageIndex") == 2){ //热门配置页不循环推送 HotConfig hotConfig = new HotConfig(s, stmt);hotConfig.sendWebSocket(json);}else if(json.getInt("pageIndex") == 3){final TrafficLog trafficLog = new TrafficLog(s, stmt);int isRealTimeSearch = json.getInt("isRealTimeSearch");if(isRealTimeSearch == 1){timer.schedule(new TimerTask() { //每隔5分钟执行一次 @Override public void run() {trafficLog.sendWebSocket(json);} }, 0, 300000); }else{ //只执行一次timer.schedule(new TimerTask() {@Override public void run() {trafficLog.sendWebSocket(json);} }, 0); }}else if(json.getInt("pageIndex") == 4){final RuleLog ruleLog = new RuleLog(s, stmt);int isRealTimeSearch = json.getInt("isRealTimeSearch");if(isRealTimeSearch == 1){timer.schedule(new TimerTask() { //每隔5分钟执行一次 @Override public void run() {ruleLog.sendWebSocket(json);} }, 0, 300000); }else{ //只执行一次timer.schedule(new TimerTask() {@Override public void run() {ruleLog.sendWebSocket(json);} }, 0); }}else{ //isp页面的请求final ISPLog ispLog = new ISPLog(s, stmt);int isRealTimeSearch = json.getInt("isRealTimeSearch");if(isRealTimeSearch == 1){timer.schedule(new TimerTask() { //每隔5分钟执行一次 @Override public void run() {ispLog.sendWebSocket(json);} }, 0, 300000); }else{ //只执行一次timer.schedule(new TimerTask() {@Override public void run() {ispLog.sendWebSocket(json);} }, 0); }}}@OnClosepublic void onClose(Session s) {log.info("Client closed");try {timer.cancel(); if (stmt != null) {stmt.close();stmt = null;}if (conn != null) {conn.close();conn = null;}} catch (SQLException e) {e.printStackTrace();}}@OnErrorpublic void onError(Throwable e) {log.error("WebSocket Error");e.printStackTrace();} }


  响应具体某个页面的请求

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.websocket.Session;
import org.apache.log4j.Logger;
import net.sf.json.JSONObject;public class HotConfig {private Session session;private Statement stmt = null;private ResultSet rs = null;private static Logger log = Logger.getLogger(HotConfig.class);public HotConfig(Session s, Statement stmt){this.session = s;this.stmt = stmt;}public void sendWebSocket(final JSONObject json){String srcIp = json.getString("srcIp");String startTime = json.getString("startTime");String endTime = json.getString("endTime");Map<String, ArrayList<Long>> params = new HashMap<String, ArrayList<Long>>();ArrayList<Long> pzID = new ArrayList<Long>();             //different chart lines nameArrayList<Long> statCount = new ArrayList<Long>();        //chart x axisArrayList<Long> pzIDReverse = new ArrayList<Long>();            //different chart lines nameArrayList<Long> statCountReverse = new ArrayList<Long>();        //chart x axistry {String srcIpCriteria = "";                        //拼接源IP SQL条件if(srcIp.length() > 0) {srcIpCriteria = " where CLIENT_IP='"+srcIp+"' ";}String startTimeCriteria = "";                    //拼接源IP SQL条件if(startTime.length() > 0) {if(srcIpCriteria.equals(""))startTimeCriteria = " where STAT_TIME >= to_date('"+startTime +"','yyyy-mm-dd hh24:mi')";elsestartTimeCriteria = " and STAT_TIME >= to_date('"+startTime +"','yyyy-mm-dd hh24:mi')";}String endTimeCriteria = "";                      //拼接源IP SQL条件if(endTime.length() > 0) {if(srcIpCriteria.equals("") && startTimeCriteria.equals(""))endTimeCriteria = " where STAT_TIME < to_date('" +endTime+"','yyyy-mm-dd hh24:mi') ";elseendTimeCriteria = " and STAT_TIME < to_date('" +endTime+"','yyyy-mm-dd hh24:mi') ";}String sql = "select * from (select PZ_ID, sum(STAT_COUNT) as sumCount from RULE_HOT_CONFIG_INFO" + srcIpCriteria + startTimeCriteria + endTimeCriteria + " group by PZ_ID order by sumCount desc) where rownum <= 50";                log.info("sql="+sql+"execute success");rs = stmt.executeQuery(sql);while(rs.next()){ pzID.add(rs.getLong(1));statCount.add(rs.getLong(2));}for(int i = pzID.size() - 1; i >= 0; i--){pzIDReverse.add(pzID.get(i));statCountReverse.add(statCount.get(i));}params.put("pzID", pzIDReverse);params.put("statCount",statCountReverse);         session.getBasicRemote().sendText(JSONObject.fromBean(params).toString());log.info("主动发给前端的数据="+JSONObject.fromBean(params).toString());} catch (IOException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}}

 

客户端

  目前主流的浏览器Firefox、Chrome已经支持WebSocket协议,这意味只不需要引用额外的js库就可以直接使用WebSocket了。

<script type="text/javascript">   
     //创建WebSocket对象,用于一开始建立连接,之后就不要再建立连接了var webSocket = new WebSocket('ws://localhost:8080/websocket/websocket');webSocket.onopen = function(event) {};webSocket.onmessage = function(event) {
        //接收来自服务器的数据,这里客户端没有发送任何请求,任何时间接收到数据都可以异步调用onMessage(event);
        var  m = JSON.parse(event.data);
        alert(m);};webSocket.onerror
= function(event) {}; function onMessage(event) {} </script>

 


 推荐学习文章:http://www.ibm.com/developerworks/cn/java/j-lo-WebSocket/

        http://www.tuicool.com/articles/7zyMvy6

        http://www.alixixi.com/web/a/2014032492868.shtml

转载于:https://www.cnblogs.com/vincent-vg/p/5831421.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254541.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程和多进程的区别(小结)

分类&#xff1a; linux 2009-06-19 09:33 11501人阅读 评论(15) 收藏 举报 很想写点关于多进程和多线程的东西&#xff0c;我确实很爱他们。但是每每想动手写点关于他们的东西&#xff0c;却总是求全心理作祟&#xff0c;始终动不了手。 今天终于下了决心&#xff0c;写点东西…

Android:日常学习笔记(8)———探究UI开发(5)

Android:日常学习笔记(8)———探究UI开发(5) ListView控件的使用 ListView概述 A view that shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view. 1.关于ArrayAdapter&#xff1a; ArrayAdapter<T> 是 ListAd…

分布式锁与实现(一)——基于Redis实现

概述 目前几乎很多大型网站及应用都是分布式部署的&#xff0c;分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和…

深入理解Activity启动流程(二)–Activity启动相关类的类图

本文原创作者:Cloud Chou. 欢迎转载&#xff0c;请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程&#xff0c;这些博客基于Cm 10.1源码研究。 在介绍Activity的详细启动流程之前&#xff0c;先为大家介绍Activity启动时涉及到的类&#xff0c;这样大家可以有大概…

5月23日

11.1 LAMP架构介绍一、LAMP架构介绍LAMP是LinuxApache(httpd)MySQLPHP的简写&#xff0c;即把Apache、MySQL以及PHP安装在linux系统上&#xff0c;组成一个运行环境来运行PHP脚本语言&#xff0c;通常是网站。比如Google、淘宝、百度、51cto博客、猿课论坛等就是用PHP语言写出来…

LaTeX基础一:安装与基本操作

一、安装 1.首先下载texlive2015.iso文件。再在解压的镜像文件中运行install-tl-advanced.bat批处理命令。注意要关闭杀毒软件&#xff0c;否则可能会出现错误。2.可以修改一下安装路径&#xff0c;只要更改一个&#xff0c;其他也随之更改&#xff1a;3.把不要安装的语言包去掉…

电路宽度测量halcon例子

一个halcon处理的例子 目录处理要求&#xff1a;原图&#xff1a;处理程序&#xff1a;处理结果&#xff1a;处理要求&#xff1a; 根据客户给的宽度&#xff0c;计算出电路宽度太窄的为NG 原图&#xff1a; 处理程序&#xff1a; read_image (Image, 1.png) rgb1_to_gray(I…

iOS显示性能优化过程讲解

点我跳转原文地址 卡顿的原理 iOS系统界面滑动流畅性的保持主要是依靠CPU和GPU两大处理硬件间通力合作的结果&#xff0c;一个视图的显示需要先经过CPU创建、布局计算、对图片解码、文本绘制&#xff0c;然后CPU将计算的结果交给GPU&#xff0c;GPU可能需要对图形进行变换、合成…

1.SoapUI接口测试--创建项目

1、点击File-->New soapUI Project 2、填写项目名称&#xff0c;接口服务地址后单击【OK】按钮后就成功创建了一个项目 3、模拟发送请求 4、创建请求 或者直接Copy一个请求 5、保存项目 6、项目是以xml的格式保存的&#xff0c;下次用的时候可以直接导入&#xff0c;点击Fil…

HTML图片元素(标记)

<html> <head> <title>第一个网页</title> </head> <body> ***************图片元素******************</br> <img srcmm.jpg /> </body> </html> 新建一个文件夹“text”,在text文件夹内新建index.html并放入一张…

ASP.NET Aries 3.0发布(附带通用API设计及基本教程介绍)

主要更新&#xff1a; 1&#xff1a;升级处理机制&#xff08;js请求由同步变更为异步&#xff09; 2&#xff1a;优化前端JS&#xff1a;包括API和配置方式。 3&#xff1a;增加InputDialog功能。 4&#xff1a;增远远程验证功能。 5&#xff1a;优化权限安全机制。 6&#xf…

甲骨文称 Java 序列化的存在是个错误,计划删除

甲骨文计划从 Java 中去除序列化功能&#xff0c;因其在安全方面一直是一个棘手的问题。 Java 序列化也称为 Java 对象序列化&#xff0c;该功能用于将对象编码为字节流...Oracle 的 Java 平台小组的首席架构师 Mark Reinhold 说&#xff1a;“删除序列化是一个长期目标&#x…

CreateProcess

Windows 进程创建完整过程&#xff08;除去细节&#xff09; 当前流程是分析WinXP x86得到的&#xff0c;在最新版本Windows上不一定正确&#xff0c;但是可以做一个参考&#xff0c; 由于我这里符号并不全&#xff0c;所以导致我这里有些东西看到的可能是错误的&#xff0c;误…

MVC架构模式(2)

简介&#xff1a; MVC最初是在Smaltalk_80中被用来构建用户界面的。M代表模型Model&#xff0c;V代表视图View&#xff0c;C代表控制器Controller。 Model模型层&#xff0c;可以简单理解就是数据层&#xff0c;用于提供数据。在项目中&#xff0c;&#xff08;简单理解&#x…

ios学习之旅---指针也不难

1、认识指针#include <stdio.h> //基本数据类型作为函数參数传递是值传递 //void moveFront(int x ,int y) //{ // x x 2; //} void test() {// 确定当前坐标int x 20;int y 150;printf("%p\n",&x);printf("%lu\n",&x);*((int *)(0…

符合skyline的3dml网络发布服务

技术交流群&#xff1a;665060698使用java web实现&#xff1b;接口符合skyline的3dml模型形式&#xff1b;通过简单的发布界面&#xff0c;直接发布3dml模型&#xff1b;实现te pro在客户端读取数据&#xff1b;实现在te pro客户端的对应查询功能&#xff1b;负载可以达到skyl…

51NOD 1125(交换机器最小代价) (贪心) 思想 !思想!

题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId1125 1125 交换机器的最小代价基准时间限制&#xff1a;1 秒 空间限制&#xff1a;131072 KB 分值: 80 难度&#xff1a;5级算法题收藏关注有N台机器重量各不相等&#xff0c;现在要求把这些机器按照…

《Python从小白到大牛》简介

《Python从小白到大牛》已经上市&#xff01; 本书是一部系统论述Python编程语言、OOP编程思想以及函数式编程思想的立体化教程&#xff08;含纸质图书、电子书、教学课件、源代码与视频教程&#xff09;。为便于读者高效学习&#xff0c;快速掌握Python编程方法。本书作者精心…

webpack学习

全局安装安装webapck npm i webpack -g 现在我们就可以全局的使用webpack命令了 webpack中基础的命令&#xff1a; webpack enter.js output.js --watch 这个命令是将enter.js打包成output.js&#xff0c;然后html只需要引用该文件就可以了看如下entry.js,这是简单的js代码。 /…

从ORA-27300,ORA-27301到ORA-00064

近期因为session数量添加&#xff0c;须要调整session&#xff0c;也就是要调整process參数。看是比較简单的一个问题&#xff0c;却遭遇了ORA-27300&#xff0c;ORA-27301。因为这个涉及到了有关内核參数kernel.sem的改动。以下是其详细描写叙述。1、故障现象OS版本号&#xf…