• WebSocket在线通信


    一.为什么要有WebSocket

    servlet,tomcat底层核心思路都是Socket

    HTML页面在刚刚开始出现的时候是静态的,不能够进行交互,后来有了JavaScript,在一
    定程度上解决了这个问题,但是JavaScript刚出现的时候并不能和服务端进行交互,直到Ajax的出现。
    Ajax有效的解决了页面和服务端进行交互的问题,不过Ajax有一个问题,就是所有的请求都必须由客户
    端发起,服务端进行响应,如果服务端有最新的消息,难以即时的发送到客户端去,在WebSocket技术
    出现之前,为了让客户端能够即时的获取服务端的数据,一般采用如下三种方案

    1.1 轮询

    最简单的一种解决方案, 就是客户端在固定的时间间隔下(一般是1秒)不停的向服务器端发送请求,查看服务端是否有最新的数据,服务端如果有最新的数据则返回给客户端,服务端如果没有则返回一个空的json或者xml文档,这种方式的实现起来简单,但是弊端也很明显,就是会有大量的无效请求,服务端的资源被大大的浪费了

    1.2 长轮询

    长连接有点类似于轮询,不同的是服务端不是每次都会响应客户端的请求,只有在服务端有最新数据的时候才会响应客户端的请求,这种方式很明显会节省网络资源和服务端资源,但是也存在一些问题,比如:

    1.如果浏览器在服务器响应之前有新数据要发送就只能创建一个新的并发请求,或者先尝试断掉当前请求然后再创建新的请求。
    2.TCP和HTTP规范中都有连接超时一说,所以所谓的长连接并不能一直持续,服务端和客户端的连接需要定期的连接和关闭再连接,当然也有一些技术能够延长每次连接的时间,这是题外话。

    1.3Applet和Flash

    Applet和Flash都已经是明日黄花了,不过这两个技术在当年除了以让我们的HTML页面更加绚丽之外,还可以解决消息推送问题Ajax这种技术去实现全双工通信已经陷入困境的时候,开发者图Apple和Flash来模拟全双工通信,开发者可以创建一个只有像素点大的普通透明的Applet或者Flash,然后将之内嵌在页中, 然后这Apple或者Flash中的代码创建出一个Socket连接种连接方式消除了HTT协议中的各种限制,当服务器有消息发到客户端的时候,开发者以在Applet或者Flash中调用JavaScript函数,并将服务器传来的消传递给JavaScript函数,然后更新页面,当浏览器有数据要发送给务器的时候,也一样,通过Applet或者Flash来传递。这种方式真正实现了全双工通信,不过也有问题,如下:

    1.浏览器必须能够运行Java或者Flash
    2.无论是Applet还是Flash都存在安全问题
    3.随着HTML5在标准在浏览器中广泛支持,Flash下架已经被提上日程

    1.4WebSocket的特点

    在这里插入图片描述

    所有的HTTP客户端(浏览器、移动端等)都可以在请求头中包Connection:Upgrade,这个表示客户端希望升级请求协议,那么希望升级成什么样的协议呢?我们需要在Upgrade头中指定一个或多个协议的列表,当然这些协议必须兼容HTTP/1.1协议。服务器收到请求之后,如果接受升级请求,那么将会返回一个101的状态码表示转换请求协议,同时在响应的Upgrade头中使用单个值,这个个值就是请求协议列表中服务器支持的第一个协议(即请求头Upgrade字段中列出来的协议列表中服务器支持的第一个协议)。HTTP升级最大的好处是最终使我们可以使用任意的协议,在升握手完成之后,它就不再使用HTTP连接了,我们甚至可以在升级握手完成之后建立一个Socket连接,理论上我们可以使用HTTP升在两个端点之间使用任何自己设计的协议,进而创建出各种各样TCP通信,当然浏览器不会让开发者随意去这么做,而是要指定某些协议,WebSocket应运而生!

    1.5 WebSocket的用途

    说了这么多那么WebSocket协议到底可以用在哪些地方呢?事实上,WebSocket协议的用途几乎是没有限制的,比如

    1.网页上的在线聊天
    2.多人在线游戏
    3.在线股票网站
    4.在线即时新闻网站
    5.高清视频流
    6.应用集群之间的通信
    7.远程系统/软件的状态和性能的实时监控

    五子棋小游戏
    在线聊天

    1.6 WebSocket的优势

    1.由于WebSocket连接在端口80(ws)或者443(wss)上创建,HTTP使用的端口相同,这样,基本上所有的防火墙都不会阻塞WebSocket连接
    2.WebSocket使用HTTP协议进行握手,因此它可以自然而然的成到网络浏览器和HTTP服务器中
    3.心跳消息(ping和pong)将被反复的发送,进而保持WebSocket连接几乎一直处于活跃状态。一般来说是这样,一个节点周期性的一个小数据包到另外一个节点(ping),而另一个节点则使用了包含相同数据的数据包作为应(pong),这样两个节点都将处于连接状态
    4.使用该协议,当消息启动或者到达的时候,服务端和客户端都以知道
    5.WebSocket连接关闭时将发送一个特殊的关闭消息
    6.WebSocket支持跨域,可以避免Ajax的限制
    7.HTTP规范要求浏览器将并发连接数限制为每个主机名两个接是当我们使用WebSocket的时候,当握手完成之后该限制就不在了因为此时的连接已经不再是HTTP连接了

    二. WebSocket的实际案例

    2.1 加入依赖

      <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4

    2.2实体类

    package com.huang.vhr.framework.web.entity;
    
    public class Chat {
        private String from;
        private String to;
        private String msg;
    
        public String getFrom() {
            return from;
        }
    
        public void setFrom(String from) {
            this.from = from;
        }
    
        public String getTo() {
            return to;
        }
    
        public void setTo(String to) {
            this.to = to;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2.3 配置类WebSocketConfig

    package com.huang.vhr.framework.comments.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
    import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
    import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
    
    @Configuration
    //开启消息代理
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        /**
         * 配置 websocket 连接地址
         * @param registry
         */
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/myws/ep")
                    //设置允许的域
                    .setAllowedOrigins("http://localhost:8080")
                    //支持前端使用 SockJS
                    .withSockJS();
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            registry.enableSimpleBroker("/queue");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2.4controller层调用底层方法

    package com.huang.vhr.controller.system.basic;
    
    
    import com.huang.vhr.framework.web.entity.Chat;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.messaging.handler.annotation.MessageMapping;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.stereotype.Controller;
    
    import java.security.Principal;
    
    @Controller
    public class ChatController {
    
        @Autowired
        SimpMessagingTemplate simpMessagingTemplate;
    
        /**
         *
         * @param chat
         * @param principal 这个就是当前登录用户对象
         */
        @MessageMapping("/myws/chat")
        public void chat(Chat chat, Principal principal) {
            chat.setFrom(principal.getName());
            //发送一条消息
            simpMessagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2.5 前端–vue

    不会前端。。
    留着先吧

  • 相关阅读:
    计算机网络原理 谢希仁(第8版)第四章习题答案
    【CAN总线】从数字设计的角度分析CAN协议1—CAN概述
    Flutter:Android/iOS集成Flutter模块
    原子物理 名词索引
    Opencv——颜色模型+通道分离与合并
    面试总结大全
    SpringBoot SpringBoot 基础篇(第一篇) 第1章 SpringBoot 入门 1.4 HelloWorld 执行分析
    JS中的防抖和节流
    微信小程序基于java实现v2支付,提现,退款
    【OSPF宣告——network命令与多区域配置实验案例】
  • 原文地址:https://blog.csdn.net/weixin_43189971/article/details/126056728