JavaWeb合集14-WebSocket

十四、WebSocket

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

HTTP协议和WebSocket协议对比:

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

应用场景:视频弹幕、网页聊天、体育实况更新、股票基金报价实时更新。

1、入门案例

实现步骤:

  1. 直接使用websocket.html页面作为WebSocket客户端

    html 复制代码
    <html>
    <body class="gray-bg">
     
    <div class="online">
    
           <input  id="text" type="text">
    
        <button onclick="send()">发送消息</button>
        <button onclick="closeWebSocket()">关闭连接</button>
    
        <div id="message"></div> 
      
    </div>
     
     
    <script th:inline="javascript">
        
        let websocket = null;
        let host = document.location.host;
        let sid=getRandomIntInclusive(0,1000000)
    
        function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; // 最小值和最大值都是包含的
    }
    
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            //连接WebSocket节点
            websocket = new WebSocket("ws://localhost:9091/ws/"+sid);
        } else {
            alert('浏览器不支持webSocket');
        }
        
        //连接发生错误的回调方法
        websocket.onerror = function () {
            setMessageInnerHTML("连接失败");
        };
        
        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            setMessageInnerHTML("连接成功");
        };
        
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            let data = event.data;
            console.log("后端传递的数据:" + data);
            //将后端传递的数据渲染至页面
             setMessageInnerHTML(data)
        };
        
        //连接关闭的回调方法
        websocket.onclose = function () {
            setMessageInnerHTML("已关闭");
        };
        
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            websocket.close();
        };
        
        //将消息显示在网页上
        function setMessageInnerHTML(innerHTML) {
            document.getElementById('message').innerHTML+=innerHTML+'<br/>'
        };
        
        //手动关闭连接
        function closeWebSocket() {
            websocket.close();
        };
        
        //发送消息
        function send() {
            let message = document.getElementById('text').value;
            websocket.send(message);
            setMessageInnerHTML("已向服务器发送内容:"+message+)
        };
        
    </script>
     
    </body>
    </html>
  2. 导入WebSocket的maven坐标

    xml 复制代码
    <!-- SpringBoot Websocket -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
  3. 导入WebSocket服务端组件WebSocketServer, 用于和客户端通信

    java 复制代码
    //主要是将目前的类定义成一个websocket服务器端(就像Controller层), 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
    @ServerEndpoint("/ws/{sid}")
    @Component
    @Slf4j
    public class WebSocketService {
    
        /**
         * 用来存放所有的webSocket连接
         */
        private static Map<String,Session> sessionMap=new HashMap<>();
    
    
        /**
         * 连接建立成功调用的方法
         *
         * @param session 会话
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("sid")String sid)  {
            System.out.println("客户端:"+sid+" 连接成功!");
            sessionMap.put(sid,session); // 将当前连接加入到连接池中
        }
    
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         */
        @OnMessage
        public void onMessage(String message, @PathParam("sid") String sid) {
            System.out.println("收到来自窗口:" + sid + "的信息:" + message);
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose(@PathParam("sid") String sid) {
            log.info("窗口:" + sid + "关闭了连接");
            sessionMap.remove(sid);  // 移除连接池中的连接
        }
    
    
        /**
         * 自定义消息推送、可群发
         *
         * @param message 消息
         */
        public static void sendAllClient(String message)  {
            System.out.println("推送消息到窗口,推送内容:" + message);
            // 遍历所有连接(获取到Map的全部vaue值,进行遍历)
            for (Session item : sessionMap.values()) {
                try {
                    item.getBasicRemote().sendText(message);  // 发送消息
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
  4. 导入配置类WebSocketConfiguration, 注册WebSocket的服务端组件

    java 复制代码
    @Configuration
    public class WebSocketConfig {
        /**
         * 这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket  ,如果你使用外置的tomcat就不需要该配置文件
         */
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }
  5. 导入定时任务类WebSocketTask, 定时向客户端推送数据

    java 复制代码
    @Component
    public class WebSocketTask {
        //将WebSocketService注入到WebSocketTask中
        @Autowired
        private WebSocketService webSocketService;
        /**
         * 每5秒执行一次
         */
        @Scheduled(cron = "0/5 * * * * ? ")
        public void webSocketService(){
            webSocketService.sendAllInfo("服务器定时推送消息: "+LocalDateTime.now());
        }
    }
相关推荐
小冷爱学习!2 小时前
华为动态路由-OSPF-完全末梢区域
服务器·网络·华为
技术小齐3 小时前
网络运维学习笔记 016网工初级(HCIA-Datacom与CCNA-EI)PPP点对点协议和PPPoE以太网上的点对点协议(此处只讲华为)
运维·网络·学习
看,未来4 小时前
Apipost 与 Postman 工具实践指南:WebSocket调试与动态参数测试
websocket·测试工具·postman
shimly1234565 小时前
tcpdump 用法示例
网络·测试工具·tcpdump
xmweisi6 小时前
【华为】报文统计的技术NetStream
运维·服务器·网络·华为认证
VVVVWeiYee6 小时前
BGP配置华为——路径优选验证
运维·网络·华为·信息与通信
yourkin6667 小时前
TCP...
服务器·网络·tcp/ip
哑巴语天雨9 小时前
前端面试-网络协议篇
websocket·网络协议·http·面试·https
绿色果酱9 小时前
利用Postman和Apipost进行WebSocket调试和文档设计
websocket·测试工具·yapi·postman
ktkiko1110 小时前
Websocket——心跳检测
网络·websocket·网络协议