websocket入门及应用

news/发布时间2024/5/15 2:21:54

websocket

When to use a HTTP call instead of a WebSocket (or HTTP 2.0)

WebSocket 是基于TCP/IP协议,独立于HTTP协议的通信协议。WebSocket 是双向通讯,有状态,客户端一(多)个与服务端一(多)双向实时响应(客户端 ⇄ 服务端)。WebSocket 是应用在浏览器的 Socket (是 Socket 模型接口的实现),Socket 是一个网络通信接口 (通信规范)。

WebSocket协议端口是80。WebSocket SSL协议端口是443。*Socket是TCP/IP协议的网络数据通讯接口(一种底层的通讯的方式)。image-20230827173621392

image-20230827180052083

引入依赖

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

定义配置类

@Configuration
public class WebsocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

定义controller

定义controller接口规范传输

public interface WebsocketHandler {void onOpen(Session session);void onClose(Session session);void onMessage(String message);
}

定义controller实现交互

package com.wnhz.wnmap.schedule.controller;import com.wnhz.wnmap.schedule.vo.MessageVo;
import com.wnhz.wnmap.schedule.common.util.JsonUtil;
import com.wnhz.wnmap.schedule.handler.WebsocketHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;@ServerEndpoint("/ws/api")
@Slf4j
public class ScheduleController implements WebsocketHandler {private Session session;private int count;@OnOpen@Overridepublic void onOpen(Session session) {this.session = session;MessageVo webMessage = new MessageVo(++count, MessageVo.MessageType.WEBSOCKET_OPEN, "websocket连接成功...");String message = JsonUtil.toString(webMessage);this.sendMessage(message);log.debug("websocket建立成功.......");}@OnClose@Overridepublic void onClose(Session session) {this.session = session;MessageVo webMessage = new MessageVo(--count, MessageVo.MessageType.WEBSOCKET_OPEN, "websocket断开连接成功...");String message = JsonUtil.toString(webMessage);this.sendMessage(message);log.debug("websocket关闭成功.......");}@OnMessage@Overridepublic void onMessage(String message) {MessageVo messageVo = new MessageVo();messageVo.setType(MessageVo.MessageType.WEBSOCKET_MESSAGE);  //类型3指信息交互messageVo.setCount(count);messageVo.setMessage(message);String json = JsonUtil.toString(messageVo);this.sendMessage(json);log.debug("[websocket消息:]收到客户端发来的消息:{}", message);}private void sendMessage(String message) {try {log.debug("[websocket服务器返回信息:] {}", message);if(Objects.nonNull(this.session)){this.session.getBasicRemote().sendText(message);}} catch (IOException e) {e.printStackTrace();}}
}

vue+wesocket

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Websocket</title><script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body><div id="app"><textarea>{{msg}}</textarea><hr/><input type="text" placeholder="请输入传输数据" v-model="sendTxt"><button @click="wsend">发送</button></div><script>new Vue({el: '#app',data() {return {websocket: null,msg: '',sendTxt: ''}},created() {this.init();},methods: {init: function () {this.websocket = new WebSocket('ws://localhost:15555/ws/api');this.websocket.onopen = this.wopen;this.websocket.onmessage = this.wMessage;this.websocket.onclose = this.wclose;},wopen: function () {console.log("socket连接成功.....")},wMessage: function (e) {console.log("接收到的信息: " + e.data )let data = eval("(" + e.data + ")"); //解析对象this.msg = data.message;},wclose: function () {console.log("websocket连接端口.....")},wsend: function () {console.log("发送新消息......" + this.sendTxt);this.websocket.send(this.sendTxt);}},destroyed() {this.websocket.onclose = this.close();}});</script></body>
</html>

image-20230827212823339

前后端交互案例

案例一

后端
public interface WebSocketHandler {void onOpen(Session session);void onClose();void onMessage(String message);
}
public class WebSocketServer implements WebsocketHandler {@OnOpen@Overridepublic void onOpen(Session session) {System.out.println("连接--->"+session);WebSocketUtil.put(session);log.debug("前端与后台建立连接:{}", this);}@OnClose@Overridepublic void close() {log.debug("前端已关闭连接:{}", this);//webSocketServers.remove(this);}@OnMessage@Overridepublic void onMessage(String message) {log.debug("接收到前端信息:{}", message);log.debug("---------向前端发送信息-----------------");//  sendMessage("[服务器:] 你好,信息从后台返回");}@RabbitListener(queues = "regist_simple_queue")public void registryUser(User user) throws Exception {System.out.println("消费--->"+user);//System.out.println("------------>"+WebSocketUtil.get());Thread.sleep(5000);WebSocketUtil.get().getBasicRemote().sendText(user.getUsername()+"已经注册成功^_^");}
}
package com.wnhz.vue.web.socket;import javax.websocket.Session;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;public class WebSocketUtil {private static final CopyOnWriteArrayList<Session> sessions = new CopyOnWriteArrayList<>();public static void put(Session session){sessions.add(session);}public static int size(){return sessions.size();}public static Session get(){return sessions.get(0);}
}
前端
<!DOCTYPE HTML>
<html>
<head><meta charset="utf-8"><title>vue发送websocket-to springboot</title><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><script src="https://cdn.jsdelivr.net/npm/vue@2"></script><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="https://unpkg.com/element-ui/lib/index.js"></script></head>
<body><div id="app"><input type="text" v-model="book.title" placeholder="书名"><input type="text" v-model="book.author" placeholder="作者"><input type="text" v-model="book.price" placeholder="价格"><input type="text" v-model="book.category" placeholder="类别"><button >运行 WebSocket</button>
</div><script>new Vue({el: '#app',data() {return {book: {title: '',author: '',price: '',category: ''},websocketPath: 'ws://localhost:9090/mysocket',ws: null}},mounted() {this.ws = new WebSocket(this.websocketPath);this.ws.onopen = this.open;this.ws.onmessage = this.getMessage;this.ws.onclose = this.close;},methods: {open: function () {this.ws.send("发送数据");console.log("websocket连接成功...");},getMessage: function (event) {let received_msg = event.data;console.log("receive: "+ received_msg);this.$message({message: received_msg,type: 'success'});},close: function () {console.log("websocket连接已经关闭")}},destroyed() {this.ws.onclose = this.close();}});
</script></body>
</html>

案例二

前端
<template><div><el-input v-model="msg" placeholder="请问您还有什么问题?"></el-input><el-button type="button" @click="wssend">发送给客服</el-button></div>
</template><script>
export default {data() {return {websocket: null,msg: ''};},created() {this.websocket = new WebSocket('ws://localhost:9999/mysocket');this.websocket.onopen = this.wsopen;this.websocket.onclose = this.wsclose;this.websocket.onmessage = this.wsmessage;},methods: {wsopen() {console.log("websocket连接成功.....")},wsclose() {console.log("websocket关闭成功.....")},wsmessage(event) {//获取后台交互console.log("===>" + event.data);this.$notify({title: '来自客服',message: event.data,duration: 2000});      },wssend() {this.websocket.send(this.msg);}}
}
</script>
后台
package com.wnhz.websocket.ws;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.ServerEndpoint;
import java.io.IOException;@Component
@ServerEndpoint("/mysocket")
@Slf4j
public class WebSocketController {/*** 建立websocket连接*/@OnOpenpublic void onOpen(Session session) throws IOException {log.debug("建立websocket连接成功,sessionId:{}",session.getId());session.getBasicRemote().sendText("[from server:]"+"I'm fine!!!");}@OnClosepublic void onClose(Session session) throws IOException {log.debug("websocket连接断开,sessionId:{}",session.getId());session.close();}@OnMessagepublic void sendMessage(Session session,String message) throws IOException {log.debug("[from web:]{}",message);if("你好".equals(message)){session.getBasicRemote().sendText("亲,您好,有什么能为您服务的^_^");}if("退货".equals(message)){session.getBasicRemote().sendText("对不起,客服繁忙中,请稍后再咨询");}}
}

应用场景

1.社交订阅

对社交类的应用的一个裨益之处就是能够即时的知道你的朋友正在做什么。虽然听起来有点可怕,但是我们都喜欢这样做。你不会想要在数分钟之后才能知道一个家庭成员在馅饼制作大赛获胜或者一个朋友订婚的消息。你是在线的,所以你的订阅的更新应该是实时的。

2.多玩家游戏

网络正在迅速转变为游戏平台。在不使用插件(我指的是Flash)的情况下,网络开发者现在可以在浏览器中实现和体验高性能的游戏。无论你是在处理DOM元素、CSS动画,HTML5的canvas或者尝试使用WebGL,玩家之间的互动效率是至关重要的。我不想在我扣动扳机之后,我的对手却已经移动位置。

3.协同编辑/编程

我们生活在分布式开发团队的时代。平时使用一个文档的副本就满足工作需求了,但是你最终需要有一个方式来合并所有的编辑副本。版本控制系统,比如Git能够帮助处理某些文件,但是当Git发现一个它不能解决的冲突时,你仍然需要去跟踪人们的修改历史。通过一个协同解决方案,比如WebSocket,我们能够工作在同一个文档,从而省去所有的合并版本。这样会很容易看出谁在编辑什么或者你在和谁同时在修改文档的同一部分。

4.点击流数据

分析用户与你网站的互动是提升你的网站的关键。HTTP的开销让我们只能优先考虑和收集最重要的数据部分。然后,经过六个月的线下分析,我们意识到我们应该收集一个不同的判断标准——一个看起来不是那么重要但是现在却影响了一个关键的决定。与HTTP请求的开销方式相比,使用Websocket,你可以由客户端发送不受限制的数据。想要在除页面加载之外跟踪鼠标的移动?只需要通过WebSocket连接发送这些数据到服务器,并存储在你喜欢的NoSQL数据库中就可以了(MongoDB是适合记录这样的事件的)。现在你可以通过回放用户在页面的动作来清楚的知道发生了什么。

5.股票基金报价

金融界瞬息万变——几乎是每毫秒都在变化。我们人类的大脑不能持续以那样的速度处理那么多的数据,所以我们写了一些算法来帮我们处理这些事情。虽然你不一定是在处理高频的交易,但是,过时的信息也只能导致损失。当你有一个显示盘来跟踪你感兴趣的公司时,你肯定想要随时知道他们的价值,而不是10秒前的数据。使用WebSocket可以流式更新这些数据变化而不需要等待。

6.体育实况更新

现在我们开始讨论一个让人们激情澎湃的愚蠢的东西——体育。我不是运动爱好者,但是我知道运动迷们想要什么。当爱国者在打比赛的时候,我的妹夫将会沉浸于这场比赛中而不能自拔。那是一种疯狂痴迷的状态,完全发自内心的。我虽然不理解这个,但是我敬佩他们与运动之间的这种强烈的联系,所以,最后我能做的就是给他的体验中降低延迟。如果你在你的网站应用中包含了体育新闻,WebSocket能够助力你的用户获得实时的更新。

7.多媒体聊天

视频会议并不能代替和真人相见,但当你不能在同一个屋子里见到你谈话的对象时,视频会议是个不错的选择。尽管视频会议私有化做的“不错”,但其使用还是很繁琐。我可是开放式网络的粉丝,所以用WebSockets getUserMedia API和HTML5音视频元素明显是个不错的选择。WebRTC的出现顺理成章的成为我刚才概括的组合体,它看起来很有希望,但其缺乏目前浏览器的支持,所以就取消了它成为候选人的资格。

8.基于位置的应用

越来越多的开发者借用移动设备的GPS功能来实现他们基于位置的网络应用。如果你一直记录用户的位置(比如运行应用来记录运动轨迹),你可以收集到更加细致化的数据。如果你想实时的更新网络数据仪表盘(可以说是一个监视运动员的教练),HTTP协议显得有些笨拙。借用WebSocket TCP链接可以让数据飞起来。

9.在线教育

上学花费越来越贵了,但互联网变得更快和更便宜。在线教育是学习的不错方式,尤其是你可以和老师以及其他同学一起交流。很自然,WebSockets是个不错的选择,可以多媒体聊天、文字聊天以及其它优势如与别人合作一起在公共数字黑板上画画…

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

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

相关文章

java数据结构与算法刷题-----LeetCode106. 从中序与后序遍历序列构造二叉树

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 1. 法一&#xff1a;递归 解题思路&#xff1a;时间复杂度O(n),空间复杂度…

运维SRE-15 自动化批量管理-ansible1

## 1.什么是自动化批量管理重复性工作与内容: 思考如何自动化完成. 部署环境,批量查看信息,批量检查:自动化 一般步骤:1.如何手动实现2.如何自动化管理工具&#xff0c;批量实现3.注意事项&#xff1a;想要自动化一定要先标准化(所有环境&#xff0c;软件&#xff0c;目录一致)…

vue+node.js美食分享推荐管理系统 io551

&#xff0c;本系统采用了 MySQL数据库的架构&#xff0c;在开始这项工作前&#xff0c;首先要设计好要用到的数据库表。该系统的使用者有二类&#xff1a;管理员和用户&#xff0c;主要功能包括个人信息修改&#xff0c;用户、美食类型、美食信息、订单信息、美食分享、课程大…

基于Python网络爬虫的IT招聘就业岗位可视化分析推荐系统

文章目录 基于Python网络爬虫的IT招聘就业岗位可视化分析推荐系统项目概述招聘岗位数据爬虫分析系统展示用户注册登录系统首页IT招聘数据开发岗-javaIT招聘数据开发岗-PythonIT招聘数据开发岗-AndroidIT招聘数据开发岗-其它招聘岗位数据分析算法方面运维方面测试方面招聘岗位薪…

xff注入 [CISCN2019 华东南赛区]Web111

打开题目 看见smarty 想到模板注入 又看见ip 想到xff注入 一般情况下输入{$smarty.version}就可以看到返回的smarty的版本号。该题目的Smarty版本是3.1.30 在Smarty3的官方手册里有以下描述: Smarty已经废弃{php}标签&#xff0c;强烈建议不要使用。在Smarty 3.1&#xff…

vue3+js 实现记住密码功能

常见的几种实现方式 1 基于spring security 的remember me 功能 ​​​​​​​ localStorage 除非主动清除localStorage 里的信息 &#xff0c;不然永远存在&#xff0c;关闭浏览器之后下次启动仍然存在 存放数据大小一般为5M 不与服务器进行交互通信 cookies 可以…

解决弹性布局父元素设置高自动换行,子元素均分高度问题(align-content: flex-start)

案例&#xff1a; <view class"abc"><view class"abc-item" v-for"(item,index) in 8" :key"index">看我</view> </view> <style lang"less">.abc{height: 100px;display: flex;flex-wrap: …

Sublime Text4配置C#运行环境

这里写自定义目录标题 前言部署.NET环境Sublime Text4配置C#编译环境1. 下载插件 运行测试 前言 今天把家里的9年前的远古神机搬了出来&#xff0c;重装了个win7的精简版&#xff0c;本打算装个VScode测试一下是否能写C#代码&#xff0c;结果是可以的&#xff0c;但&#xff0…

ESP8266智能家居(4)——开发APP基础篇

1.前期准备 安装好Android studio 开发环境 准备一台完好的安卓手机 手机要处于开发者模式 设置 --->关于手机---> 一直点击版本号 &#xff08;不同手机进入开发者模式的步骤可能不太一样&#xff09; 进入开发者模式后&#xff0c;找到辅助功能&#xff0c;打开开…

C++基础学习——哈希表的封装

目录 ​编辑 一&#xff0c;实现一个可封装的哈希表 1&#xff0c;哈希表的节点 2&#xff0c;哈希表的成员 3&#xff0c;哈希表成员方法的实现 4&#xff0c;迭代器的实现 5&#xff0c;在哈希表中加入迭代器 二&#xff0c;封装哈希表 1&#xff0c;unorder_map封装 2…

HarmonyOS—代码Code Linter检查

Code Linter代码检查 Code-Linter针对ArkTS/TS代码进行最佳实践、编程规范方面的检查&#xff0c;目前还会检查ArkTS语法规则。开发者可根据扫描结果中告警提示手工修复代码缺陷&#xff0c;或者执行一键式自动修复&#xff0c;在代码开发阶段&#xff0c;确保代码质量。 检查…

unity学习(41)——创建(create)角色脚本(panel)——UserHandler(收)+CreateClick(发)——发包!

1.客户端的程序结构被我精简过&#xff0c;现在去MessageManager.cs中增加一个UserHandler函数&#xff0c;根据收到的包做对应的GameInfo赋值。 2.在Model文件夹下新增一个协议文件UserProtocol&#xff0c;内容很简单。 using System;public class UserProtocol {public co…

基于django的购物商城系统

摘要 本文介绍了基于Django框架开发的购物商城系统。随着电子商务的兴起&#xff0c;购物商城系统成为了许多企业和个人创业者的首选。Django作为一个高效、稳定且易于扩展的Python web框架&#xff0c;为开发者提供了便捷的开发环境和丰富的功能模块&#xff0c;使得开发购物商…

基于Java SSM框架实现高校网课管理系统项目【项目源码+论文说明】

基于java的SSM框架实现高校网课管理系统演示 摘要 随着移动应用技术的发展&#xff0c;越来越多的学生借助于移动手机、电脑完成生活中的事务&#xff0c;许多的行业也更加重视与互联网的结合&#xff0c;以提高教学的教育水平和寻求更高的经济利益。针对高校网课管理系统&…

EI论文联合复现:含分布式发电的微网/综合能源系统储能容量多时间尺度线性配置方法程序代码!

适用平台&#xff1a;Matlab/Gurobi 程序提出了基于线性规划方法的多时间尺度储能容量配置方法&#xff0c;以满足微电网的接入要求为前提&#xff0c;以最小储能配置容量为目标&#xff0c;对混合储能装置进行容量配置。程序较为基础&#xff0c;算例丰富、注释清晰、干货满满…

[linux]进程间通信(IPC)———共享内存(shm)(什么是共享内存,共享内存的原理图,共享内存的接口,使用演示)

一、什么是共享内存 共享内存区是最快的&#xff08;进程间通信&#xff09;IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到内核&#xff0c;换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。注意&#xff1a;…

亿道丨三防平板丨加固平板丨三防加固平板丨改善资产管理

库存资产管理中最重要的部分之一是准确性&#xff1b;过时的库存管理技术会增加运输过程中人为错误、物品丢失或纸张损坏的风险。如今随着三防平板电脑的广泛使用&#xff0c;库存管理也迎来了好帮手&#xff0c;通过使用三防平板电脑能够确保库存管理、数据存储和记录保存的准…

Linux-用户和权限(黑马学习笔记)

认识root用户 root用户&#xff08;超级管理员&#xff09; 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 ● 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#xff09; ● 而在前期&#xff0c;我们一直…

apidoc接口文档的自动更新与发布

文章目录 一、概述二、环境准备三、接口文档生成1. 下载源码2. 初始化3.执行 四、文档发布五&#xff0c;配置定时运行六&#xff0c;docker运行 一、概述 最近忙于某开源项目的接口文档整理&#xff0c;采用了apidoc来整理生成接口文档。 apidoc是一个可以将源代码中的注释直…

AWS安全组是什么?有什么用?

最近看到小伙伴在问&#xff0c;AWS安全组是什么&#xff1f;有什么用&#xff1f;今天我们大家就来简单聊聊&#xff0c;仅供参考哦&#xff01; AWS安全组是什么&#xff1f;有什么用&#xff1f; 【回答】&#xff1a;AWS安全组是一种虚拟防火墙&#xff0c;用于控制进出…
推荐文章