websocket实战

pom

:

xml 复制代码
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.53</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
<!--            <version>1.3.5.RELEASE</version>-->
        </dependency>

前端页面1

html 复制代码
<!DOCTYPE HTML>
<html>
<head>
    <title>My WebSocket</title>
</head>

<body>
Welcome<br/>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>

<script type="text/javascript">
    var websocket = null;

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

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

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

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

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

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

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

    //关闭连接
    function closeWebSocket(){
        websocket.close();
    }

    //发送消息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

前端页面2:

html 复制代码
<!DOCTYPE HTML>
<html>
<head>
    <title>My WebSocket</title>
</head>

<body>
Welcome<br/>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>

<script type="text/javascript">
    var websocket = null;

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

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

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

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

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

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

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

    //关闭连接
    function closeWebSocket(){
        websocket.close();
    }

    //发送消息
    function send(){
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

config配置类:

java 复制代码
package com.example.demo.config;

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

/**
 * @Author LHM
 * @Date 2024/9/27 11:25
 * @Description TODO
 */
@Configuration
public class WebsocketAutoConfig {

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

controller层:

java 复制代码
package com.example.demo.controller;


import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{id}")
public class WebsocketServerEndpoint {
     //在线连接数,应该把它设计成线程安全的
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
    public static CopyOnWriteArraySet<WebsocketServerEndpoint> websocketServerSet
            = new CopyOnWriteArraySet<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //会话窗口的ID标识
    private String id = "";
    
     /**
     * 链接成功调用的方法
     */
     @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) {
        log.info("onOpen >> 链接成功");
        this.session = session;
        //将当前websocket对象存入到Set集合中
        websocketServerSet.add(this);
        //在线人数+1
        addOnlineCount();
        log.info("有新窗口开始监听:" + id + ", 当前在线人数为:" + getOnlineCount());
        this.id = id;
        try {

            sendMessage("有新窗口开始监听:" + id + ", 当前在线人数为:" + getOnlineCount());
        } catch (Exception e) {
            log.error(e.toString());
        }


    }
     /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        log.info("onClose >> 链接关闭");
        //移除当前Websocket对象
        websocketServerSet.remove(this);
        //在内线人数-1
        subOnLineCount();
        log.info("链接关闭,当前在线人数:" + getOnlineCount());
    }
     /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("接收到窗口:" + id + " 的信息:" + message);

        //发送信息
        for (WebsocketServerEndpoint websocketServerEndpoint : websocketServerSet) {
            try {
                websocketServerEndpoint.sendMessage("接收到窗口:" + id + " 的信息:" + message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable e) {
        e.printStackTrace();
    }
    /**
     * 推送消息
     *
     * @param message
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    
    private void subOnLineCount() {
        WebsocketServerEndpoint.onlineCount--;
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    private void addOnlineCount() {
        WebsocketServerEndpoint.onlineCount++;
    }

    private void sendObject(Object object) throws IOException, EncodeException {
        this.session.getBasicRemote().sendObject(object);
    }
//   /** id为null时是群发
//     * @param map
//     * @param id
//     */
    public static void sendData(String id, Object map) {
        for (WebsocketServerEndpoint endpoint : websocketServerSet) {
            try {
                if (id == null) {
                    endpoint.sendObject(map);
                } else if (endpoint.id.equals(id)) {
                    endpoint.sendObject(map);
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }



}

    

发送数据:

java 复制代码
package com.example.demo.demos;


import com.example.demo.controller.WebsocketServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Configuration
@EnableScheduling
public class SendMessageToWeb {
//    @Autowired
//    WebsocketServerEndpoint websocketServerEndpoint;
 
    //每10秒发送一次
    @Scheduled(cron = "0/10 * * * * ?")
    public void sendTestMessage() {
        if(WebsocketServerEndpoint.websocketServerSet.size()>0){
            log.info("发送数据");
            try{
                //这里省略获取到需要发送数据data的逻辑  
                CopyOnWriteArraySet<WebsocketServerEndpoint> set =  WebsocketServerEndpoint.websocketServerSet;
                       for (WebsocketServerEndpoint s:set) {
                        s.sendMessage("zzz:" + System.currentTimeMillis());
                       }
            }catch (Exception e){
                log.error(e.getMessage());
            }
        }
    }
}
相关推荐
shmily ....23 分钟前
文件上传漏洞原理
网络·安全
wang090735 分钟前
netty编程之实现websocket客户端并发送二进制消息
websocket·netty实现ws客户端
IPFoxy6661 小时前
如何判断静态代理IP地址是否被污染?
网络·安全·web安全
滔滔不绝tao1 小时前
五子棋双人对战项目(6)——对战模块(解读代码)
spring boot·websocket
网络研究院1 小时前
什么是 ARP 欺骗和缓存中毒攻击?
网络·安全·ddos·攻击·arp·实践·缓解
没有名字的小羊1 小时前
网络通信——OSPF和RIP的区别(总结)
网络·网络协议
it00zyq2 小时前
Linux网络编程
linux·网络
Play_Sai5 小时前
【信息安全管理与评估】2023年全国职业院校技能大赛赛题第02套
网络
梆子井欢喜坨6 小时前
《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 12数据中心中的EVPN
网络·云原生