zoukankan      html  css  js  c++  java
  • 写一个简易的java项目(五) websocket 弹幕 -1

    目的:websocket做弹幕 

    用到的技术:springboot +websocket +uniapp (只写了后台)

    菜鸟:https://www.runoob.com/html/html5-websocket.html

    这是最后结果的展示:

    WebSocket是什么?为什么用它?

    全双工通信的协议。允许服务端主动向客户端推送数据。

    后台代码:

    第一步:依赖

        <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>

    第二步:配置

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

    第三步:WebSocketServer 这里是重点

    群发

    @ServerEndpoint("/socketServer/{userId}")
    @Component
    @Slf4j
    public class BatchWebSocketServer {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<BatchWebSocketServer> webSocketSet = new CopyOnWriteArraySet<BatchWebSocketServer>();
    
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
    
        //接收userId
        private String userId="";
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session,@PathParam("userId") String userId) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数+1
            log.info("用户:"+userId+",当前在线人数为" + getOnlineCount());
            this.userId=userId;
            try {
                sendMessage("连接成功");
            } catch (IOException e) {
                log.error("IO异常");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数-1
            log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         * @param message 接收消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
            log.info("收到来自窗口"+userId+"的信息:"+message);
            //群发消息
            for (BatchWebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("error");
            error.printStackTrace();
        }
        /**
         * 实现服务器主动推送
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
        /**
         * 群发消息
         * */
        public static void sendInfo(String message,@PathParam("userId") String userId){
            log.info("推送消息"+userId+",报文:"+message);
            for (BatchWebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            BatchWebSocketServer.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            BatchWebSocketServer.onlineCount--;
        }
    }

    前台参考 : uniapp ,这里不写太详细了。

    https://uniapp.dcloud.io/api/request/websocket

    做个参考:

    import base from '@/config/baseUrl';
    import store from '@/store';
    class socket {
        constructor(options) {
            //地址
            this.socketUrl = base.socketUrl;
            this.socketStart = false;
            this.monitorSocketError();
            this.monitorSocketClose();
            this.socketReceive();
        }
        init(callback) {
            const _this = this;
            if (base.socketUrl) {
                if(this.socketStart){
                    console.log('webSocket已经启动了');
                }else{
                    uni.connectSocket({
                        url: this.socketUrl,
                        method: 'GET'
                    });
                    uni.onSocketOpen((res) => {
                        this.socketStart = true;
                        callback && callback();
                        console.log('WebSocket连接已打开!');
                    });
                    /* setTimeout(() => {
                        _this.getHeartbeat();
                    }, 5000); */
                }
            }else{
                console.log('config/baseUrl socketUrl为空');
            }
        }
        //Socket给服务器发送消息
        send(data, callback) {
            const _this = this;
            if (store.state.userInfo.uid) {
                data.userUid = store.state.userInfo.uid;
            }
            console.log(data);
            uni.sendSocketMessage({
                data: JSON.stringify(data),
                success: () => {
                    callback && callback(true);
                },
                fail: () => {
                    callback && callback(false);
                }
            });
        }
        //Socket接收服务器发送过来的消息
        socketReceive() {
            const _this = this;
            uni.onSocketMessage(function(res) {
                let data = JSON.parse(res.data);
                console.log('收到服务器内容:', data.type);
                _this.acceptMessage && _this.acceptMessage(data.type);
            });
        }
        //关闭Socket
        closeSocket() {
            uni.closeSocket();
            _this.socketStart = false;
        }
        //监听Socket关闭
        monitorSocketClose() {
            const _this = this;
            uni.onSocketClose(function(res) {
                console.log('WebSocket 已关闭!');
                _this.socketStart = false;
                setTimeout(function() {
                    _this.init();
                }, 3000);
            });
        }
        //监听Socket错误
        monitorSocketError() {
            const _this = this;
            uni.onSocketError(function(res) {
                _this.socketStart = false;
                console.log('WebSocket连接打开失败,请检查!');
            });
        }
        //心跳
        getHeartbeat() {
            const _this = this;
            this.send({
                type: "心跳",
                userUid: store.state.userInfo.userUid
            }, (val) => {
                setTimeout(() => {
                    if (val) {
                        _this.getHeartbeat();
                    } else {
                        _this.init();
                    }
                }, 10000);
            });
        }
    };
    const mySocket = new socket();
    export default mySocket;

    @

  • 相关阅读:
    Android EditText 文本框实现搜索和清空效果
    Android学习笔记之打钩显示输入的密码
    Mysql limit offset
    Android SDK更新以及ADT更新出现问题的解决办法
    Android Broadcast Receiver 使用入门
    立即执行函数
    JS 原型 & 继承
    JS 对象
    chrome extension overview
    JS 修改元素
  • 原文地址:https://www.cnblogs.com/DarGi2019/p/13948044.html
Copyright © 2011-2022 走看看