IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Websocket-【聊天室的原理,接收消息提醒/ 公告消息】 -> 正文阅读

[网络协议]Websocket-【聊天室的原理,接收消息提醒/ 公告消息】

Websocket是什么样的协议,具体有什么优点
首先,WebSocket是HTML5出的东西(协议),Websocket是一个持久化的协议,?而HTTP是一种非持久的协议
?

服务器推送消息到前端实现页面数据实时刷新项目链接如下:https://blog.csdn.net/pengff1234/article/details/114520623
?

websocket的使用步骤:

  • ? ? 建立websocket连接后,
  • ? ? 客户端(前端)可以发送指令给后端,
  • ? ? 后端如果有数据就返回,
  • ? ? 此时前端可以接收到消息,进行音频的播放

实现步骤

? ?1: 案例:【实现--实时接收消息提醒并语音播报】

??从此连接下载必须的js:https://gitee.com/jqn-room/case-code/tree/master/websocket/static
? sockjs.min.js 和???stomp.min.js

/*
  audio音频: 
     src:是音频路径,
     preload:是否预加载,
     muted:静音,现在浏览器不支持自动播放音频,
     autoplay:自动播放,即便音频你没有设置为静音,在页面加载的时候也不会播放音频的。
     因此先设置为静音,然后需要播放音频的时候,将音频的静音取消,然后重置音频从头开始进行播放即可。
*/

<template>
  <div id="wrap">
    <p>
      <audio src="./remind.mp3" id="audio" preload="auto" muted autoplay type="audio/mp3" controls="controls">
           <span id="audioId">播放音乐</span>
      </audio>
    </p>
  </div>
</template>
<script src="dist/js/sockjs.min.js"></script>
<script src="dist/js/stomp.min.js"></script>
<script>
  export default {
    data () {
      return : {}
    },
    methods: {
      websocket () {
         var websocket = null;
        // 1: websocket 实例化
        // 判断当前浏览器是否支持websocket
        if ("websocket" in window) {
            websocket = new WebSocket("wss://echo.websocket.org");
            //上面的这个"wss://echo.websocket.org"是从别的地方找来的,后端会提供的……,此时仅用于测试使用

           // 2: websocket建立连接
           var setIntervalWesocketPush = null;
           websocket.onopen = (e) => {
              console.log("建立连接");//建立连接后,send发送消息给后端,具体的内容可以前后端定义好,此处为"ping"
              clearInterval(setIntervalWesocketPush);//下面的代码是清理定时器,并重启定时器,每隔15s发送一次消息
              websocket.send("ping"); // 发送消息
              setIntervalWesocketPush = setInterval(() => {
                 websocket.send("ping");
              }, 15000);
           };
           //后端接收到消息后,可以发送数据给前端,前端就可以接收到了
           

           // 3: websocket 接收消息
           websocket.onmessage = (e) => {
              console.log("收到消息:" + e.data);
              // 获取音频:之前我都是用$("#audio")获取音频,但是执行:$("#audio").play()方法是会报错
              var audio = document.querySelector("audio");//用这种标签名称获取的方式就不会报错了,,,,
              audio.currentTime = 0;//从头开始播放
              audio.muted = false;//取消静音
              audio.play();//音频播放
           };

           // 4: websocket 通信错误
           websocket.onerror = (e) => {
              alert("websocket通信发生错误");
           };

           // 5: websocket 关闭连接
           websocket.onclose = (e) => {
               console.log("连接关闭");
               clearInterval(setIntervalWesocketPush);
               websocket.close(); // 关闭WebSocket连接
           };
        } else {
            alert("您的浏览器不支持websocket")
        }
      } 
    },
    mouted () {
      window.addEventListener('unload', e => this.unloadHandler(e))
      this.websocket()
    },
    destroyed() {
      window.removeEventListener('unload', e => this.unloadHandler(e))
    }
  }
</script>

? ?2: 案例2 【实现一个实时聊天功能】
? ? ? 项目链接地址:https://gitee.com/jqn-room/case-code/tree/master/websocket/websockChat-master

问题拓展:
我想实现用户登录之后一直保持websocket连接,也就是多页面共享一个websocket,当其他户给他发信息时后端立马就转发给他,如果不在线,就存储消息,等他上线在发给他,这个功能怎么实现呢???

答:?可以在登录的时候,在根页面(或者在多页面外再包一层页面)里面建立websocket连接,后端收到消息可以先判断当前这个人是否有对应session存在,用户是否在线。

不在线可以先存redis或者数据库,等到下一次用户登录建立sockekt的时候再进行判断 和 发送。

前端通过socket收到消息再去进行对应的业务展示或者业务调用


WebSocket模拟库插件:SockJS

01 SockJS简介

  • 在传输方式的选择方面,SockJS 会优先采用 websocket,然后再自动降级;
  • 其 API 几乎与 websocket API 的使用方式相同;
  • 兼容跨浏览器,支持跨域。

? ? ? SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器?不支持 WebSocket?的情况下,也可以很简单地实现WebSocket的功能的,方法就是使用 SockJS。该库可以模拟对 WebSocket 的支持,实现浏览器和 Web 服务器之间低延迟、全双工、跨域的通讯通道。

它会?优先选择WebSocket?进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。

幸运的是,我们不需要知道这些方案都代表什么,只需要简单地设置就可以使用了。

?实现步骤如下:

服务端-后端
启动WebSocket的配置中,你需要做的所有事情就是加上 withSockJS()


public void registerWebSocketHandlers(WebSocketHandlerRegistry) {
? ? ?// withSockJS 声明启用支持 sockJS
? ? ?webSocketHandlerRegistry.addHandler(marcoHandler(), "/echo").withSockJS();
}

客户端-前端
在客户端需要引入SockJS库,然后把 new WebSocket(url); 替换成 new SockJS(url);

SockJS类 和 WebSocket类是兼容的,所以可以直接替换

<template>
  
</template>

<script>
import SockJS from 'sockjs-client'
import Stomp from 'stompjs'
export default {
    data () {
        return {
            ws: null,
            username: '',
            identity: '',
            stompClient: null,
            userId: '',
            auctionData: {
                landId: ''
            }
        }
    },
    methods: {
        // 创建连接方法
        connection (url, headers) { // 建立连接
            // 动态的连接地址 url 和 订阅的数据 headerData
            if ('WebSocket' in window) {
                // 建立连接对象
                const socket = new SockJS(url)
                // 获取STOMP子协议的客户端对象
                this.stompClient = Stomp.over(socket)
                this.stompClient.connect(headers, this.callbackSuccess, this.callbackError)
            } else {
                alert('当前浏览器 Not support websocket')
            }
        },
        callbackSuccess () { // websocket的返回成功的方法,可在里面进行具体的监听接口和路径的配置
            console.log('建立连接成功')
            // subscribe订阅服务端提供的某个topic(主题)
            this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/auctionStart/getResponse', (msg) => {
                // 业务操作
            })
            // subscribe订阅服务端提供的某个topic(主题)
            this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/rotationSettlement/getResponse', (msg) => {
                // 业务操作
            })
            // subscribe订阅服务端提供的某个topic(主题)
            this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/auctionOver/getResponse', (msg) => {
                // 业务操作
            })

            // 监听轮次完成
            this.stompClient.subscribe('/topic/' + this.auctionData.auctionId + '/rotationOver/getResponse', (msg) => {
                // 业务操作
            })

            // 完成一个流程 开启新轮询
            this.stompClient.subscribe('/user/' + this.userId + '/' + this.auctionData.auctionId + '/getResponse', (res) => {
                console.log(res + 'user')
                const result = JSON.parse(res.body)
                if (result.code === 200) {
                    this.query() // 完成后新业务逻辑,或创建新的轮询等
                } else {
                    console.log(result.msg)
                }
            })
        },
        callbackError (err) { // websocket的返回失败的方法
            console.log(err)
            this.disconnect(); // 断开连接
        },
        disconnect () { // 断开连接的方法
            console.log(this.stompClient)
            if (this.stompClient) {
                this.stompClient.disconnect()
                this.stompClient = null
            }
        },
        // 根据状态判断是否开始通信
        initConnect () {
            var url
            if (location.hostname === '192.168.10.143' ||
                location.hostname === 'localhost' ||
                location.hostname === '127.0.0.1') {
                url = 'http://121.40.115.212' // 本地测试地址
            } else {
                url = `https://${location.hostname}/proxy` // 线上地址
            }
            this.connection( // 开始连接
                `${url}/api/development/websocket/ws`,
                { name: this.userId, landId: this.auctionData.landId }
            )
        }
    },
    mounted() {
        this.initConnect()
    },
    beforeDestroy() {
        // 在页面关闭或销毁时关闭socket
        this.disconnect(); // 断开连接
    }
}
</script>

<style>

</style>

需要做的事情就是这么多

效果展示
1:? ?支持 WebSocket
? ? ? 当浏览器 和 服务器都支持 websocket 的时候,直接使用websocket连接

2:? 不支持WebSocket

不支持WebSocket的场景有:

? ? ?浏览器不支持
? ? ?Web容器不支持,如tomcat7以前的版本不支持WebSocket
? ? 防火墙不允许
? ? ?Nginx没有开启WebSocket支持


当遇到不支持WebSocket的情况时,SockJS会尝试使用其他的方案来连接,刚开始打开的时候因为需要尝试各种方案,所以会阻塞一会儿,之后可以看到连接有异常,那就是尝试失败的情况。

为了测试,我使用Nginx做反向代理,把www.test.com指到项目启动的端口上,然后本地配HOST来达到模拟真实场景的效果。

因为Nginx默认是不支持WebSocket的,所以这里模拟出了服务器不支持WebSocket的场景。

参考资料:https://segmentfault.com/a/1190000019409827
? ? ? ? ? ? ? ? ? ? ??

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 12:18:17  更:2021-09-03 12:20:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:32:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码