WebSocket笔记

news2024/12/27 10:47:39

1. websocket介绍

WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。

HTTP协议和WebSocket协议对比:

  • HTTP是短连接
  • WebSocket是长连接
  • HTTP通信是单向的,基于请求响应模式
  • WebSocket支持双向通信
  • HTTP和WebSocket底层都是TCP连接

在这里插入图片描述

WebSocket缺点:

  • 服务器长期维护长连接需要一定的成本
  • 各个浏览器支持程度不一
  • WebSocket 是长连接,受网络限制比较大,需要处理好重连
  • 应用场景:
    1). 视频弹幕 2). 网页聊天 3). 股票基金报价实时更新 等等…

2. 简单入门案例

**需求:**实现浏览器与服务器全双工通信。浏览器既可以向服务器发送消息,服务器也可主动向浏览器推送消息。

  1. 导入maven坐标
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 客户端-编码前端代码
    可放在Resource目录下的page目录
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
</head>
<body>
    <input id="text" type="text" />
    <button onclick="send()">发送消息</button>
    <button onclick="closeWebSocket()">关闭连接</button>
    <div id="message">
    </div>
</body>
<script type="text/javascript">
    var websocket = null;
    var clientId = Math.random().toString(36).substr(2);

    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
        //连接WebSocket节点
        websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
    }
    else{
        alert('Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };

    //连接成功建立的回调方法
    websocket.onopen = function(){
        setMessageInnerHTML("连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function(){
        websocket.close();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //发送消息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
	
	//关闭连接
    function closeWebSocket() {
        websocket.close();
    }
</script>
</html>
  1. 服务端-定义配置类,注册WebSocket的服务端组件
package com.zsx.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocket配置类,用于注册WebSocket的Bean
 */	
@Configuration
public class WebSocketConfiguration {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}
  1. 服务端-定义WebSocket服务端组件
package com.zsx.websocket;

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.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服务
 */
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    //存放会话对象
    private static  Map<String, Session> sessionMap = new HashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("sid") String sid, Session session){
        System.out.println("客户端:" + sid + "建立连接");
        sessionMap.put(sid, session);
    }


    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(@PathParam("sid") String sid, String message){
        System.out.println("接收到客户端:" + sid + "发送的消息:" + message);
    }

    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void opClose(@PathParam("sid") String sid){
        System.out.println("客户端:" + sid + "关闭连接");
        sessionMap.remove(sid);
    }

    /**
     * 群发
     *
     * @param message
     */
    public void sendToAllClient(String message){
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
  1. 定义定时任务类,定时向客户端推送数据(模拟服务器主动向客户端发消息)
package com.sky.task;

import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class WebSocketTask {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 通过WebSocket每隔5秒向客户端发送消息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}
  1. 资源文件映射-这个主要是为了能直接在浏览器打开上面的websocket.html网页(http://localhost:8081/page/websocket.html)
package com.zsx.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    /**
     * 设置静态资源映射
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始进行静态资源映射..");
        registry.addResourceHandler("/page/**").addResourceLocations("classpath:/page/");
    }

}

启动类

package com.zsx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class WebSocketDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebSocketDemoApplication.class, args);
        System.out.println("项目启动...");
    }
}
  1. 效果测试
    1)启动服务,打开websocket.html页面
    在这里插入图片描述
    2)服务端接收到消息
    在这里插入图片描述

进一步了解的案例可参考 https://gitee.com/zhou-shaoxiong/Spring-websocket/blob/master/pom.xml

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

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

相关文章

iOS--动静态库

文章目录 认识动静态库静态库动态库静态的打包静态库的使用动态库的打包动态库的使用 动静态库的本质就是可执行程序的"半成品"。 需要完成一个可执行程序需要经历以下四个步骤: 预处理:完成头文件的展开&#xff0c;去掉注释&#xff0c;宏替换&#xff0c;条件编译…

微信小程序学习笔记(五)——优化

下拉刷新后主动关闭 Page({onPullDownRefresh: function() {// ...wx.stopPullDownRefresh()} })在发起请求时设置 loading&#xff0c;请求结束后关闭 Page({onLoad: function(options) {wx.showLoading({title: 数据加载中...}) // 展示 loadingwx.request({// ...complete: …

leetcode每日一练-第206题-反转链表

一、思路 迭代 二、解题方法 以输入为 1 -> 2 -> 3 -> 4 -> 5 的链表为例 三、code class Solution { public:ListNode* reverseList(ListNode* head) {ListNode* prevnullptr;//反转后的链表ListNode* currhead;//当前更新的原有链表while(curr)//原有链表无值…

【大模型】更强的 LLaMA2 来了,开源可商用、与 ChatGPT 齐平

【大模型】可商用且更强的 LLaMA2 来了 LLaMA2 简介论文GitHubhuggingface模型列表训练数据训练信息模型信息 许可证参考 LLaMA2 简介 2023年7月19日&#xff1a;Meta 发布开源可商用模型 Llama 2。 Llama 2是一个预训练和微调的生成文本模型的集合&#xff0c;其规模从70亿到…

中间件安全-CVE漏洞复现-Weblogic+JBoss+GlassFish

服务攻防测试流程&#xff1a; 使用vulfocus靶场&#xff1a; 案例演示&#xff1a;中间件-Weblogic-工具梭哈 探针默认端口&#xff1a;7001&#xff0c;Weblogic是Oracle公司推出的J2EE应用服务器 使用vulfocus靶场复现漏洞 漏洞&#xff1a;weblogic-cve_2020_14883 启动环…

自然语言处理:赋予AI理解和交流的能力

文章目录 &#x1f340;引言&#x1f340;NLP的定义与重要性&#x1f340;NLP的应用领域&#x1f340;学好自然语言处理需要掌握以下知识&#x1f340;GPT和自然语言处理&#x1f340;总结 &#x1f340;引言 自然语言处理&#xff08;Natural Language Processing&#xff0c;…

Visual Studio创建Web项目时候报错- 找不到“2.0.1“版本的程序包”解决方法

问题描述 在今天我开始想做一个ASP.Net Web 项目时&#xff0c;在创建项目的时候突然报下面这个错&#xff0c;也是试了很多方法&#xff0c;比如卸载重新安装&#xff0c;安装更高版本&#xff0c;我之前用的是2019版本&#xff0c;后面下载了2022的&#xff0c;又出现了新的…

python与深度学习(三):ANN和fashion_mnist

目录 1. 说明2. fashion_mnist实战2.1 导入相关库2.2 加载数据2.3 数据预处理2.4 数据处理2.5 构建网络模型2.6 模型编译2.7 模型训练2.8 模型保存2.9 模型评价2.10 模型测试2.11 模型训练结果的可视化 3. fashion_mnist的ANN模型可视化结果图4. 完整代码 1. 说明 本篇文章是A…

(202307)wonderful-sql:环境搭建(ubuntu 22.04 + mysql 8.0 + workbench/dbeavar,免密码-不建议免哈)

前言 能够再次参加datawhale组织的开源学习是十分兴奋的&#xff0c;看到datawhale能够越办越好我也是由衷地感到高兴。 这次参加的是mysql的学习&#xff0c;我知道这样短期的学习不会对我的能力造成多么大的提升&#xff0c;但是相信经过这次学习&#xff0c;我又将被datawh…

Kubernetes中Pod的扩缩容介绍

Kubernetes中Pod的扩缩容介绍 在实际生产系统中&#xff0c;我们经常会遇到某个服务需要扩容的场景&#xff0c;也可能会遇到由于资源紧张或者工作负载降低而需 要减少服务实例数量的场景。此时可以利用 Deployment/RC 的 Scale 机制来完成这些工作。 Kubernetes 对 Pod 的扩…

java代码审计1之环境搭建

文章目录 1、安装jdk2、配置tomcat3、配置maven3.1、配置环境变量3.2、配置源和maven配置文件 4、idea4.1、配置maven4.2、新建web项目4.3、遇到的问题(弹出404页面) 之前的文章&#xff0c; https://blog.csdn.net/weixin_43970718/article/details/121929434 https://blog.…

(全网最详细!)mysql、redis 、RabbitMQ只能本机访问,怎么改?

如果只能本机访问&#xff0c;怎么改? 一、mysql - 改my.ini 刷脚本 bind-address0.0.0.0 然后重启一下mysql服务 任务管理器-关掉mysql 搜索 计算机管理-重启mysql服务 然后 打开查询&#xff0c;并选择mysql数据&#xff0c;输入这个sql语句&#xff0c;点击运行 sele…

POC!VMWare RCE CVE-2023-20887

漏洞简介 VMWare Aria Operations for Networks (vRealize Network Insight) 在通过 Apache Thrift RPC 接口接受用户输入时容易受到命令注入的攻击。此漏洞允许远程未经身份验证的攻击者以 root 用户身份在底层操作系统上执行任意命令。RPC 接口受可以绕过的反向代理保护。VM…

vue3+vue-router4:报错Uncaught (in promise) Error: Invalid navigation guard

报错图示&#xff1a; Error: Invalid navigation guard Uncaught (in promise) Error: Invalid navigation guard 错误影响描述&#xff1a; 配置开发、测试、生产时候&#xff0c;因为是公众号&#xff0c;所以想在开发环境下免鉴权&#xff0c;不走微信获取openid接口&a…

PHP要怎么学--【思维导图知识范围】

强撸项目 总目录在此 专辑工作量PHP登陆/php登录–【强撸项目】难度★✫✰✰✰PHP注册/登录/发邮件–【强撸项目】★★★✫✰PHP在线相册–【强撸项目】★★★★✫–【强撸项目】––【强撸项目】––––– 文章目录 本系列校训学习资源的选择环境的问题本人推荐 PHP视频的知…

C语言-分支语句和循环

目录 【1】字符输入输出 【2】C语言下的垃圾字符回收 【3】分支语句 【4】循环 练习&#xff1a; 【1】字符输入输出 按字符的输入输出 int getchar(void); 功能&#xff1a;从终端输入一个字符 参数&#xff1a;无 返回值&#xff1a;输入字符的ASCII值int putchar(int…

pandas常用方法

一、提要 pandas对于处理表格类数据来说是非常方便的模块&#xff0c;同时也是做数据分析绕不开的第三方库。这里将工作中常用到的各种处理方法记录下来二、常用方法 接下来的以 df 表示我们要处理的 dataframe 表格数据 1、取值 # 循环遍历取值 for i in range(len(df)):y…

Spring Cloud之Gateway网关应⽤

使⽤⽹关对静态化微服务进⾏代理&#xff08;添加在它的上游&#xff0c;相当于隐藏了具体微服务的信息&#xff0c;对外暴露的是⽹关&#xff09;。 1. 右键⽗⼯程【 yx-parent 】选择【 New 】 - 【 Module 】选项&#xff0c;然后选择创建【 Maven 】类型项⽬&#xff08;不…

以高质量产业载体为底色,绘就珠海高新区产业发展新图景

【作者】珠海高新招商 “珠海高新招商”以招商运营为核心&#xff0c;聚焦珠海工业园区、珠海5.0产业园等招商引资工作&#xff0c;依托专业的招商团队和丰富的创新资源&#xff0c;为企业提供产业园入驻、平台搭建、产业政策咨询、科技服务等全流程专业服务。推动高新区招商引…

17 数组动态初始化

动态初始化&#xff1a;初始化时只指定数组长度&#xff0c;由系统为数组分配初始值。 格式&#xff1a;数据类型[] 数组名 new 数据类型[数组长度] package demo;public class Demo11 {public static void main(String[] args) {// 动态初始化数组&#xff1a;数据类型[] 数…