websocket使用

websocket

    • 1. 概述
    • 2. websocket的用法
    • 3. js代码实现
    • 4. 服务器端代码实现

maven下载地址:

https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket

1. 概述

  • 什么是websocket
 - WebSocket是一种网络传输协议,
可在单个TCP连接上进行全双工通信,位于OSI模型的应用层。- WebSocket使得客户端和服务器之间的数据交换变得更加简单,
允许服务端主动向客户端推送数据。- 在WebSocket API中,浏览器和服务器只需要完成一次握手,
两者之间就可以创建持久性的连接,并进行双向数据传输。
  • 简介
WebSocket:
建立一次连接即可
连接断开 不会自动重连(心跳机制)
双向发送数据
WebSocket实现比较复杂(使用jar包)
  • sse与websocket的优点
SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。
SSE 默认支持服务器断线重连,WebSocket 需要自己实现。
SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
SSE 支持自定义发送的消息类型
  • sse与websocket的区别
SSE 与 WebSocket 作用相似,
都是建立浏览器与服务器之间的通信渠道,
然后服务器向浏览器推送信息。总体来说,WebSocket 更强大和灵活。
因为它是全双工通道,可以双向通信;
SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。
如果浏览器向服务器发送信息,就变成了另一次 HTTP 请求

2. websocket的用法

1.启动webSocket服务
2.使用js发送数据 (使用了心跳机制保持连接)
3.webSocket服务收到消息将消息发送给指定webSocket

3. js代码实现

  • js实现(假如现在有一个叫jack的用户连接服务器)
/*** jack 连接服务器websocket js文件*/var websocket = '';
var ajaxPageNum = 1;
var last_health;
var health_timeout = 10;
var tDates = [], tData = [];
var rightIndex;if (window.WebSocket) {// 创建websocket连接  当前连接协议 ip 端口websocket = new WebSocket(encodeURI('ws://' + document.domain + ':8888'));websocket.onopen = function() {console.log('已连接');// 作为标识告诉服务器websocket.send("onlinejack");// 心跳机制 每分钟连接服务器heartbeat_timer = setInterval(function() {keepalive(websocket)}, 60000);};websocket.onerror = function() {console.log('连接发生错误');};websocket.onclose = function() {console.log('已经断开连接');initWs();};// 消息接收 接收到服务器websocket发来的消息websocket.onmessage = function(message) {console.log(message)console.log(message.data)var jsonMsg = JSON.parse(message.data);console.log(jsonMsg);// 业务代码};
} else {alert("该浏览器不支持提醒。<br/>建议使用高版本的浏览器,<br/>如 IE10、火狐 、谷歌  、搜狗等");
}// 上面的代码封装
var initWs = function() {if (window.WebSocket) {websocket = new WebSocket(encodeURI('ws://' + document.domain + ':8888'));websocket.onopen = function() {console.log('已连接');websocket.send("onlinejack");heartbeat_timer = setInterval(function() {keepalive(websocket)}, 60000);};websocket.onerror = function() {console.log('连接发生错误');};websocket.onclose = function() {console.log('已经断开连接');initWs();};// 消息接收websocket.onmessage = function(message) {console.log(message)console.log(message.data)// 业务代码};} else {alert("该浏览器不支持提醒。<br/>建议使用高版本的浏览器,<br/>如 IE10、火狐 、谷歌  、搜狗等");}
}// 心跳包
function keepalive(ws) {var time = new Date();if (last_health != -1 && (time.getTime() - last_health > health_timeout)) {// ws.close();} else {if (ws.bufferedAmount == 0) {ws.send('connect again from jack...');}}
}

4. 服务器端代码实现

  • websocket连接池
package websocket;import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import org.java_websocket.WebSocket;public class WsPool {private static final Map<WebSocket, String> wsUserMap = new HashMap<WebSocket, String>();/*** 通过websocket连接获取其对应的用户* * 根据连接对象获得连接对象对应的订单号* @param conn* @return*/public static String getUserByWs(WebSocket conn) {return wsUserMap.get(conn);}/*** 根据userName获取WebSocket,这是一个list,此处取第一个* 因为有可能多个websocket对应一个userName(但一般是只有一个,因为在close方法中,我们将失效的websocket连接去除了)* 根据订单号找到对应的连接对象websocket* * @param user*/public static WebSocket getWsByUser(String userName) {Set<WebSocket> keySet = wsUserMap.keySet();synchronized (keySet) {for (WebSocket conn : keySet) {String cuser = wsUserMap.get(conn);if (cuser.equals(userName)) {return conn;}}}return null;}/*** 向连接池中添加连接* * @param inbound*/public static void addUser(String userName, WebSocket conn) {wsUserMap.put(conn, userName); // 添加连接}/*** 获取所有连接池中的用户,因为set是不允许重复的,所以可以得到无重复的user数组* * @return*/public static Collection<String> getOnlineUser() {List<String> setUsers = new ArrayList<String>();Collection<String> setUser = wsUserMap.values();for (String u : setUser) {setUsers.add(u);}return setUsers;}/*** 移除连接池中的连接* * @param inbound*/public static boolean removeUser(WebSocket conn) {if (wsUserMap.containsKey(conn)) {wsUserMap.remove(conn); // 移除连接return true;} else {return false;}}/*** 向特定的用户发送数据* * @param user* @param message*/public static void sendMessageToUser(WebSocket conn, String message) {if (null != conn && null != wsUserMap.get(conn)) {conn.send(message);}}/*** 向所有的用户发送消息* 广播* * @param message*/public static void sendMessageToAll(String message) {Set<WebSocket> keySet = wsUserMap.keySet();synchronized (keySet) {for (WebSocket conn : keySet) {String user = wsUserMap.get(conn);if (user != null) {conn.send(message);}}}}
}
  • websocket服务器 对用户的操作
package websocket;import java.net.InetSocketAddress;import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;public class WsServer extends WebSocketServer {public WsServer(int port) {super(new InetSocketAddress(port));}public WsServer(InetSocketAddress address) {super(address);}@Overridepublic void onOpen(WebSocket conn, ClientHandshake handshake) {// ws连接的时候触发的代码,onOpen中我们不做任何操作}@Overridepublic void onClose(WebSocket conn, int code, String reason, boolean remote) {//断开连接时候触发代码userLeave(conn);System.out.println(reason);}@Overridepublic void onMessage(WebSocket conn, String message) {//客户端发送消息给服务器,自动执行此方法System.out.println(message);//服务器端发送消息给客户端,//conn.send("消息内容");if(null != message &&message.startsWith("online")){userJoin(conn,message);//用户加入}else if(null != message && message.startsWith("offline")){userLeave(conn);}}@Overridepublic void onError(WebSocket conn, Exception ex) {//错误时候触发的代码System.out.println("on error");ex.printStackTrace();}/*** 去除掉失效的websocket链接* @param conn*/private void userLeave(WebSocket conn){WsPool.removeUser(conn);}/*** 将websocket加入用户池* @param conn* @param userName*/private void userJoin(WebSocket conn,String userName){WsPool.addUser(userName, conn);}}
  • 配置websocket启动 8080port(这里使用过滤器)
package filter;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;import org.java_websocket.WebSocketImpl;import websocket.WsServer;public class StartWebSocket implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException {}@Overridepublic void init(FilterConfig arg0) throws ServletException {this.startWebSocketInstantMsg();}/*** 启动websocket 服务*/public void startWebSocketInstantMsg() {System.out.println("开始启动webSocket服务...");WebSocketImpl.DEBUG = false;// 端口WsServer server = new WsServer(8888);server.start();}}
  • 发送消息为demo
// websocket向客户端发送消息
// 根据用户名找到 用户和服务器连接到的websocket对象
WebSocket wsConn = WsPool.getWsByUser("online" + toName);
// 发送单条消息
msg.setMsgDate(new Timestamp(System.currentTimeMillis()));
// System.out.println(wsConn + "\t" + JSON.toJSONString(msg));
WsPool.sendMessageToUser(wsConn, JSON.toJSONString(msg));	

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

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

相关文章

深度学习与自然语言处理

&#xff08;纯属为了记录自己学习的点滴过程&#xff0c;引用资料都附在参考列表&#xff09; 1 传统方法的局限 1.1 传统方法的套路 传统方法的处理流程简单来说就是&#xff1a;特征提取传统机器学习模型训练&#xff1b; 特征提取&#xff1a; 使用了特征模板、TF-IDF、…

linux 烧写(1)

第一部分: 一、BootLoader的概念 BootLoader是系统加电启运行的第一段软件代码&#xff0e;回忆一下PC的体系结构我们可以知道&#xff0c;PC机中的引导加载程序由BIOS&#xff08;其本质就是一段固件程序&#xff09;和位于硬盘MBR中的引导程序一起组成。BIOS在完成硬件检测和…

利用websocket实现一对一聊天

一对一聊天websocket1. 效果展示2. 业务分析&#xff08;逻辑展示...&#xff09;3. 技术点功能 即时发送消息||随时发送消息历史消息显示已读未读状态 1. 效果展示 由于没做登录&#xff0c;就以jack和rose两人聊天 两人可相互发消息 持续输出. . 当只有jack在线时 嘤…

中文分词--词典分词--最长匹配

&#xff08;个人学习笔记&#xff0c;慎重参考&#xff09; 1 基本概念 中文分词 指的是将一段文本拆分为一系列单词的过程&#xff0c;这些单词顺序拼接后等于原文本。 作为中文信息处理的第一站&#xff0c;是后续nlp任务的基础&#xff0c;中文分词算法大致可分为词典规则…

css3动画animation,transition

animation demo1 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>animation动画</title><style>#div1 {width: 100px;height: 100px;background-color: pink;position: absolute;top: 10%;left: 25%;}/* 延迟…

PLSQL Developer 运用Profiler 分析存储过程性能

最近应公司需要&#xff0c;需要编写ORACLE存储过程。本人新手&#xff0c;在完成存储过程的编写后&#xff0c;感觉需要对存储过程中各个语句的执行时间进行分析&#xff0c;以便 对整个存储过程进行优化。 由于用的是PLSQL Developer 客户端工具&#xff0c;而网上大多介绍的…

四、Dynamic-programming algorithm Dynamic--LCS

(学习笔记&#xff0c;无什参考价值&#xff01;) 1 问题 2 算法 2.1 Brute-force LCS algorithm 检查每一个subsequence是否是yyy的子列时&#xff0c;遍历yyy的每一个元素&#xff0c;看是否依次可以全部覆盖subsequence所有元素&#xff0c;所以其复杂度为O(n)O(n)O(n); …

Spring JdbcTemplate Curd

curd1. 实现步骤2. maven dependency3. curd代码database: oracledataSource: alibaba druid 1. 实现步骤 1. 导入spring-jdbc 和 spring-tx(事务)坐标 2. 创建数据库表和实体 3.创建JdbcTemplate对象JdbcTemplate jdbc new JdbcTemplate();jdbc.setDataSource(dataSource);…

linux环境配置与使用合集

配置linux和samba共享 1.  安装linux操作系统 2.  通过windows操作系统ping linux看看是否可以ping通 3.  相关软件安装 a. 安装samba sudo apt-get install samba4, sudo apt-get install system-config-samba b. 安装ssh&#xff0c;这样windows可以远程登录linux, sud…

五、分治法应用--矩阵乘法

1 朴素算法 这个算法就是矩阵乘法的定义&#xff1a; 很容易看出这个算法复杂度是Θ(n3)\Theta(n^3)Θ(n3)。 2 递归算法 分治法首先是从分割问题开始的&#xff0c;得到数学上的递归关系后&#xff0c;然后使用递归的方式实现。 由上面的数学性质&#xff0c;可以使用递…

POJ 1300 Door Man(欧拉回路的判定)

题目链接 题意 &#xff1a; 庄园有很多房间&#xff0c;编号从0到n-1,能否找到一条路径经过所有开着的门&#xff0c;并且使得通过门之后就把门关上&#xff0c;关上的再也不打开&#xff0c;最后能回到编号为0的房间。 思路 &#xff1a; 这就是一个赤裸裸的判断欧拉通路的问…

bootstrap guide

bootstrap1. bootstrap 简单介绍2. demo演示3. 关于bootstrap使用注意的点1. bootstrap 简单介绍 起源 来自Twitter&#xff0c;是目前最受欢迎的前端框架。基于HTML、CSS、Javascript。Bootstrap js组件依赖于jquery 3.X简洁灵活&#xff0c;使得Web开发更加快捷。官网 https…

六、Analysis of quicksort

1 引言 如题目所示&#xff0c;本节的精华在于用数学解决一个直觉上看似纷乱复杂的问题&#xff0c;里面有一些一般性的分析方法&#xff0c;如引入Indicator变量&#xff0c;从而把不确定问题引入到概率框架进行分析&#xff0c;一步一步把直觉上混乱的问题理清楚&#xff0c…

Javaweb maven项目tomcat报错: javax.naming.NamingException: 无法创建资源实例

报错地址 2. 原因分析 1. Resource注解无效&#xff0c;注入失败&#xff0c;你得从容器中把bookInfoServie取去来&#xff0c;用getBean的方式创建BookInfoServiceImpl对象 2.删掉Resource注解&#xff0c;重新部署搞定。3.不要在意写了个Contorller, 初学spring&#xff0c;…

如何给APK文件签名

转载地址&#xff1a;http://www.apkbus.com/forum.php?modviewthread&tid1264211.签名的意义   为了保证每个应用程序开发商合法ID&#xff0c;防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序&#xff0c;我们需要对我们发布的APK文件进行唯一…