webSocket原理及其案例

常见的消息推送方式

1:轮询方式

浏览器以指定的时间间隔向服务器发出HTTP请求,服务器实现试试返回数据给浏览器

缺点:数据有延时、服务器压力较大。

2:长轮询

浏览器发出ajax(异步)请求,服务器接收端接收到请求后,会阻塞请求直到有数据或者超时才返回。

缺点:

3:SSE服务器发送事件

SSE在服务器和客户端之间打开一个单向通道

服务端响应的不再是一次性的数据包,而是Text/event-stream类型的数据流信息

服务器有数据变更时将数据流式传输到客户端

4:webSocket

基于TCP连接上及逆行全双工通信的协议

全双工:允许数据在两个方向上同时传输。

半双工:允许数据在两个方向上传输,但是同一个时间段内只允许一个方向上的传输。

websocket API

客户端【浏览器】API

websocket对象提供的方法

send() 通过websocket对象调用该方法发送数据给服务端

案例

服务端API

Tomcat从7.0.5才支持websocket

Java WebSocket应用由一系列的Endpoint组成,Endpoint是一个Java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体websocket消息的接口

定义Endpoint两种方式:

编程式,继承类javax.websocket.Endpoint并实现其方法。

注解式,定义一个POJO,并添加@ServiceEndpoint相关注解。

Endpoint实例在WebSocket握手时创建,并在客户端于服务端链接过程中有效,最后在链接关闭时结束。在Endpoint接口中明确定义了与其生命周期相关的方法,规范实现者确保生命周期的各个阶段调用示例的相关方法,生命周期方法如下:

方法描述注解
onOpen()当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法@OnOpen
onClose()当会话关闭时调用@OnClose
onError()当连接过程异常时调用@OnError

两个问题

服务端如何接收客户端发送的数据呢?

1:编程式

通过添加MessageHandler消息处理器来接收消息

2:注解式

在定义Endpoint时,通过@OnMessage注解指定接收消息的方法

服务端如何推送数据给客户端呢?

发送消息则由RemoteEndpoint完成,其实例由Session维护。

发送消息有两种方式

1:通过session.getBasicRemote获取同步消息发送的实例,然后调用其sendXxx()方法发送消息

2:通过session.getAsyncRemote获取异步消息发送实例,然后调用其sendXxx()方法发送消息

例子

代码实现

引入依赖资源

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.0.0.RELEASE</version>
</dependency>

编写配置类,扫描添加有@ServerEndpoint注解的Bean

@Configuration
public class FileManageWebSocketConfigMessage {/*** 注入ServerEndpointExporter,自动注册使用@ServerEndpoint注解的* @return*/public ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

编写配置类,获取HttpSession对象

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {//强转HttpSession httpSession =(HttpSession) request.getHttpSession();//将httpSession对象存储到配置对象中config.getUserProperties().put(HttpSession.class.getName(),httpSession);}

使用

在@ServerEndpoint注解种引入配置器

@ServerEndpoint(value="/chat",configurator = GetHttpSessionConfigurator.class)

案例代码

webSocket.util

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;@Component
@ServerEndpoint("/webSocket/{uId}")
@Slf4j
public class WebSocketServerUtil {private Session session;private static CopyOnWriteArraySet<WebSocketServerUtil > webSocketSet = new CopyOnWriteArraySet<>();private static ConcurrentHashMap<Long,WebSocketServerUtil > webSocketMap  = new ConcurrentHashMap<>();private Long uId = null;@OnOpenpublic void onOpen(Session session, @PathParam("uId") Long uId){this.session = session;this.uId = uId;if(webSocketMap .containsKey(uId)){webSocketMap .remove(uId);webSocketMap .put(uId,this);}else{webSocketMap .put(uId,this);webSocketSet.add(this);}log.info("【websocket消息】有新的连接,总数:{}",webSocketMap.size());}@OnClosepublic void onClose(){if(webSocketMap.containsKey(uId)){webSocketMap.remove(uId);//从set中删除webSocketSet.remove(this);}log.info("【websocket消息】连接断开,总数:{}",webSocketSet.size());}@OnMessagepublic void onMessage(String message){log.info("【websocket消息】收到客户端发来的消息:{}",message);}public void sendMessage(String message){try {this.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}/*** 发送自定义消息* */public static void sendInfo(String message,Long uId) throws Exception {//log.info("发送消息到:"+uId+",报文:"+message);if(webSocketMap.containsKey(uId)){webSocketMap.get(uId).sendMessage(message);}else{log.error("用户"+uId+",不在线!");throw new Exception("连接已关闭,请刷新页面后重试");}}
}

调用Util方法

        Long uId = new Long("1");Map msgMap = new HashMap();msgMap.put("step",1);msgMap.put("type",2);msgMap.put("msg","hello");WebSocketServerUtil.sendInfo(JsonUtil.toJson(msgMap),uId);

前端JS代码

/*** 初始化websocket连接*/
function initWebSocket() {let uId = 1;var websocket = null;if('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8009/webSocket"+uId );} else {alert("该浏览器不支持websocket!");}websocket.onopen = function(event) {console.log("建立连接");websocket.send('Hello WebSockets!');}websocket.onclose = function(event) {console.log('连接关闭')reconnect(); //尝试重连websocket}//建立通信后,监听到后端的数据传递websocket.onmessage = function(event) {let data = JSON.parse(event.data);//业务处理....if(data.step == 1){alert(data.msg);}}websocket.onerror = function() {// notify.warn("websocket通信发生错误!");// initWebSocket()}window.onbeforeunload = function() {websocket.close();}
// 重连
function reconnect() {console.log("正在重连");// 进行重连setTimeout(function () {initWebSocket();}, 1000);
}

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

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

相关文章

这是啥?也太秀了吧?

1 请坐下2 这是什么愿望&#xff0c;感觉老天都看不下去了&#xff01;3 像极了手机落在上铺的你&#xff01;4 真正智慧家居&#xff0c;免通电。5 你以为它是土豆&#xff0c;其实。。6 葫芦不一定叫葫芦葫芦有各种奇奇怪怪的形状和名字7 我发光去了&#xff01;你点的每个赞…

php七牛分片上传_利用七牛的php SDK分片上传时如何处理Notify?

我的代码如下&#xff0c;有填写相应的Rio_PutExtra&#xff0c;但是进度貌似没有输出来&#xff1f;请问是哪里写的不对么&#xff1f;…function upload($bucket, $key, $file, $type"file"){$qiniu_key "…AK…";$qiniu_sec "…SK…";Qiniu…

python课程思路_学习python课程第二十六天

一. 传输层在上述三层协议中我们,ip协议帮我们定位到子网络. mac地址帮我们定位到一台计算机,并与其通讯,但本质上,计算机的通讯是为了应用程序能够通讯,而一台计算机上不可能运行一个应用程序问题:就像我们同时运行QQ软件和微信软件, 当计算机收到一个数据包时, 需要知道这…

爱数应用容灾部署方案三

级联复制的异地容灾方案部署 爱数应用容灾部署方案可在异地部署远程容灾站点实现远程应用容灾方案&#xff0c;采用级联复制模型&#xff0c;在本地和远程分别部署容灾站点&#xff0c;克服实时复制对带宽延迟较高的缺点&#xff0c;获得最佳的容灾效果。并且可根据用户的网络和…

c# 按位与,按位或

最近在园子里看到了这篇文章&#xff0c;看完这篇会有意外收获&#xff1a;C#枚举高级战术https://mp.weixin.qq.com/s/yipaL6Acil-uxq_bDDgdyg想起了很久之前的自己的一篇总结&#xff0c;特地找出来------在工作中遇到按位或组合权限串。一直不是特别明白。今天终于花了半个下…

poj3160

http://poj.org/problem?id3160 题意读懂是关键&#xff0c;he chould choose to enter and give out a gift and hear the words from the recipient, or bypass the room in silence.通过这句话知道当收礼者给予的反应是负值时可以不加&#xff0c;flymouse decided to choo…

30张不明觉厉的照片,看几遍终于看懂了

全世界只有3.14 % 的人关注了爆炸吧知识网络上很多照片&#xff0c;虽然没经过PS&#xff0c;第一眼还是会觉得诡异。仔细看看才发现....哇噢&#xff01;总觉得她的头上有一撮尖尖的毛&#xff1f;狗狗怎么做得出这个表情&#xff1f;震惊&#xff01;发现没脖子的长颈鹿&…

域名服务器(DNS)工作原理

域名服务器工作原理 引言 只要您在互联网上发送电子邮件或浏览Web&#xff0c;您就会用到域名服务器&#xff0c;而您自己可能都不知道您在使用它们。域名服务器&#xff08;即DNS&#xff09;是互联网的相当重要且完全隐藏的部分&#xff0c;并且很神奇。域名服务器系统在全球…

排序集合的一个小坑

原来一直用SortList&#xff0c;SortedDictionary来作为键值对存储的排序集合来用&#xff0c;心中就默认是以key按ascall排序来存放的&#xff0c;在之前的案例中也没有出现问题&#xff0c;在最近一个demo中&#xff0c;打破了原来的自以为是的认识&#xff0c;因为在key中不…

python distplot 图_Python可视化23 |seaborn.distplot公司单变量分布图(直方图|核密度图),23seaborndistplot...

本文介绍seaborn.distplot绘制单变量分布图&#xff1b;之前文章介绍的核密度图(kernel density estimate (KDE))以及二者结合图。目录本文内容概要直方图核密度图直方图结合核密度图1、seaborn.distplotseaborn.distplot(a, binsNone,histTrue,kdeTrue,rugFalse, fitNone, his…

绘制矩形php,PHP_php绘制一个矩形的方法,本文实例讲述了php绘制一个矩 - phpStudy...

php绘制一个矩形的方法本文实例讲述了php绘制一个矩形的方法。分享给大家供大家参考。具体实现方法如下&#xff1a;//1、创建画布$im imagecreatetruecolor(300,200);//新建一个真彩色图像&#xff0c;默认背景是黑色&#xff0c;返回图像标识符。另外还有一个函数 imagecrea…

爱是天时地利的迷信

1 别人撒娇你撒娇2 据说套着这个白袋子晒鞋鞋就不会发黄了。。3 蚂蚁&#xff1a;为什么要欺负我&#xff01;4 这是天空的心电图吗5 有回应的喜欢真好 6 随主人这事儿原来是真的…7 被别人喜欢时的心理活动图自回忆专用小马甲你点的每个赞&#xff0c;我都认真当成了喜欢

如何做到 byte[] 和 十六进制 互转?

咨询区 alextansc&#xff1a;请问我如何实现将 byte[] 和 十六进制的string 进行互转&#xff1f;回答区 balrob&#xff1a;如果你的程序是基于 .NET5 的&#xff0c;可以使用 Convert 下新增的两个方法 ToHexString 和 FromHexString &#xff0c;参考下面两个方法的定义。/…

转载 Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget

当图片过大&#xff0c;或图片数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget&#xff0c;要想正常使用则需分配更少的内存&#xff0c;具体的解决办法是修改采样值BitmapFactory.Options.inSampleSize&#xff0c;例如&a…

Juniper Firewall多进单出配制实例

Technorati 标签: juniper,多进单出,配置实例,firewallJuniper firewall多進單出配置。想法是這樣的用一台firewall將這幾條ISP線路都接入&#xff0c;再通過一個trunk口出來&#xff0c;通過一台L2 switch劃分出幾個VLAN&#xff0c;分別對應不同的ISP線路。這樣做的好處就不多…

php js 复选框选中,为每个选中的复选框显示相同的一组问题。 (PHP和JS / Jquery)...

你可以这样做&#xff0c;它可以帮助你......HTMLfunction show_ques() {var i $(this).attr(id).substr(-1);if ($(this).is(":checked")) {//get total count of question listvar nQue $("#quelist").find("div[class^que]").length;var is…

刷题≠学好数学,近百位名校名师告诉你,数学是怎么学好的?

▲ 点击查看 数学是个神奇的科目&#xff0c;它存在着一种“梯次掉队”的现象。不是说你低年级的知识学好了&#xff0c;高年级的知识就一定能学好。相信大家都有这种体会&#xff1a;一二年级孩子成绩不相上下&#xff0c;但到三四年级的时候&#xff0c;有一批学生的数学成绩…

android 系统之ContentProvider

基于上一篇的数据库操作&#xff0c;又写了一个ContentProvider的示例。把SQLiter 的数据提供出去供别的项目进行访问。 这一篇的代码要求熟悉SQLiter 的API. 首先&#xff0c;我们编写一个类extents ContentProvider &#xff0c;重写他的方法。 URI 在http 中我们称为统一资源…

你是中层管理者?嗯,一个表面看似风光,实际却很 “鸡肋” 的重要岗位

这是头哥侃码的第246篇原创每年的六七月份&#xff0c;上海都会进入梅雨季节。这段时期的上海天气就好比大小姐的脾气&#xff0c;阴晴不定&#xff0c;完全看心情做事&#xff0c;心情好的时候&#xff0c;给你个阳光&#xff0c;让你的生活和休闲时光多一些灿烂&#xff0c;心…

20150203一些移动端H5小bug解决

都是一些我也不知道为什么会有的bug。 1. 在三星note2&#xff0c;小米2&#xff0c;页面加载后&#xff0c;页面有黑块. 那么提高被盖住的部分z-index。 2. iphone5 &#xff0c;ios7.0.4&#xff0c;上文字显示不出 那么就先hide&#xff0c;setTimeout几百毫秒再show