Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
525 views
in Technique[技术] by (71.8m points)

为什么这个websocket会一分钟就断掉,是前端问题还是后端问题?是要写心跳吗,怎么写这个心跳?

封装后的websocket:

var webSocket = null;
var globalCallback = null;//定义外部接收数据的回调函数
// var lockReconnect = false;  //避免ws重复连接
//心跳检测
// var heartCheck = {
//     timeout: 5000, //1分钟发一次心跳
//     timeoutObj: null,
//     serverTimeoutObj: null,
//     reset: function(){
//         clearTimeout(this.timeoutObj);
//         clearTimeout(this.serverTimeoutObj);
//         return this;
//     },
//     start: function(){
//         var self = this;
//         this.timeoutObj = setTimeout(function(){
//             //这里发送一个心跳,后端收到后,返回一个心跳消息,
//             //onmessage拿到返回的心跳就说明连接正常
//             webSocket.send("ping");
//             console.log("ping!")
//             self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
//                 webSocket.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
//             }, self.timeout)
//         }, this.timeout)
//     }
// };
// function reconnect(url) {
//     if(lockReconnect) return;
//     lockReconnect = true;
//     setTimeout(function () {//没连接上会一直重连,设置延迟避免请求过多
//         initWebSocket(url);
//         lockReconnect = false;
//     }, 5000);
// }

//初始化websocket
function initWebSocket(url) {
    if ("WebSocket" in window) {
        webSocket = new WebSocket(url);//创建socket对象
        console.log(webSocket);
    } else {
        alert("该浏览器不支持websocket!");
    }
    //打开
    webSocket.onopen = function() {
        // heartCheck.reset().start();//心跳检测重置
        webSocketOpen();
    };
    //收信
    webSocket.onmessage = function(e) {
        // heartCheck.reset().start();//拿到任何消息都说明当前连接是正常的
        console.log("收到消息啦:" + e.data);
        // if(e.data!='pong'){
        //     let data = JSON.parse(e.data);
        // }
        webSocketOnMessage(e);    
    };
    //关闭
    webSocket.onclose = function(e) {
        // reconnect(wsUrl);
        // reconnect(url);
        webSocketClose(e);
    };
    //连接发生错误的回调方法
    webSocket.onerror = function() {
        // reconnect(wsUrl);
        // reconnect(url);
        console.log("WebSocket连接发生错误");
    };
}

//连接socket建立时触发
function webSocketOpen() {
    //在此次定义好需要传过去的数据,先发送一个数据过去,data为与后端协议的数据类型
    const data = {
        type: "CONNECT",
        // token: sessionStorage.getItem("token") || ""
        token: localStorage.getItem("token") || ""
    };
    sendSock(data, function() {});//调用发送数据的函数
    console.log("WebSocket连接成功");
}

//客户端接收服务端数据时触发,e为接受的数据对象
function webSocketOnMessage(e) {
    // const data = JSON.parse(e.data);//根据自己的需要对接收到的数据进行格式化
    const data = e.data;
    console.log("e.dataaaaa", data);
    globalCallback(data);//将data传给在外定义的接收数据的函数,至关重要。
    /*在此函数中还可以继续根据项目需求来写其他东西。 比如项目里需要根据接收的数据来判断用户登录是否失效了,此时需要关闭此连接,跳转到登录页去。*/
}

//发送数据
function webSocketSend(data) {
    console.log("e.data>>>", data);
    //  setTimeout(() => {
    //     webSocket.send(JSON.stringify(data));
    // }, 1000);
    webSocket.send(JSON.stringify(data));//在这里根据自己的需要转换数据格式
    // webSocket.send(data);//在这里根据自己的需要转换数据格式
}
    
//关闭socket
function webSocketClose(e) {
    // CloseEvent.code: code是错误码,是整数类型
    // CloseEvent.reason: reason是断开原因,是字符串
    // CloseEvent.wasClean: wasClean表示是否正常断开,是布尔值。一般异常断开时,该值为false
    console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean)//打印断开原因
    console.log(123,e)//打印断开原因
     setTimeout(() => {
        initWebSocket(e.currentTarget.url); 
    }, 1000);
    //建立了多个socket,就做了一些判断。
    // if (
    //     webSocket.readyState === 1 &&
    //     webSocket.url === "ws://1xx.xx.xx.xxx:8088/ws"
    // ) {
    //     webSocket.close();//这句话是关键,一直没有真正的关闭socket
    //     console.log("对话连接已关闭");
    // }
}


//在其他需要socket地方调用的函数,用来发送数据及接受数据
function sendSock(sendData,callback) {
    // console.log("sendData>>>",sendData);
    // console.log("callback>>>",callback);
    // debugger;
    globalCallback = callback;//此callback为在其他地方调用时定义的接收socket数据的函数,此关重要。
    //此处先判断socket连接状态
    //下面的判断主要是考虑到socket连接可能中断或者其他的因素,可以重新发送此条消息。
    switch (webSocket.readyState) {
    //CONNECTING:值为0,表示正在连接。
    case webSocket.CONNECTING:
        setTimeout(function() {
            webSocketSend(sendData,callback);
            // console.log("sendData",sendData);
            // console.log("callback",callback);
        }, 1000);
        break;
        //OPEN:值为1,表示连接成功,可以通信了。
    case webSocket.OPEN:
        webSocketSend(sendData);
        // console.log("sendData1",sendData);
        // console.log("callback1",callback);
        break;
        //CLOSING:值为2,表示连接正在关闭。
    case webSocket.CLOSING:
        setTimeout(function() {
            webSocketSend(sendData,callback);
            // console.log("sendData2",sendData);
            // console.log("callback2",callback);
        }, 1000);
        break;
        //CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
    case webSocket.CLOSED:
        setTimeout(function() {
            initWebSocket(sendData,callback);
            // console.log("sendData3",sendData);
        }, 1000);
        // do something
        break;
    default:
        // this never happens
        break;
    }
}
//将初始化socket函数、发送(接收)数据的函数、关闭连接的函数export出去
export default {
    initWebSocket,
    webSocketClose,
    sendSock,
};

在其他组件中调用:

export default {
    name: "eveAlarmBox",
    data() {
        return {
            depId: '', //部门id
            wsUrl: "ws://217.177.257.301:10211?type=alarm:00&depId=",
            wsType: "CONNECT",
            tableData: [],           
        };
    },
    created(){
        //获取用户登录的部门id
        let userInfo = localStorage.getItem('userInfo');
        this.depId = JSON.parse(userInfo).depid;
        this.socketApi.initWebSocket(this.wsUrl + this.depId);
        //data为和后端商量好的数据格式
        const data = {
            type: this.wsType,
            msg: "心跳内容",
        };
        setTimeout(()=>{
            this.websocketSend(data);
        },1000);
    },
    methods:{
        // 接收socket回调函数返回数据的方法,服务端返回的数据
        getConfigResult(res) {
            this.tableData.push(JSON.parse(res));
        },
        websocketSend(data) {
            //data为要发送的数据,this.getConfigResult为回调函数,用于在此页面接收socket返回的数据。 
            this.socketApi.sendSock(data,this.getConfigResult);
        },  
    },
    // beforeRouteLeave(to, from, next) {
    //     //在离开此页面的时候主动关闭socket
    //     this.socketApi.webSocketClose();
    //     next();
    // },
};

image
问题:为什么这个websocket会一分钟就断掉,是前端问题还是后端问题?注释掉的那个心跳代码感觉像是死循环,不太对;
需求:断掉后会重连,是要写心跳吗,怎么写这个心跳?请各位前端大佬帮帮忙


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

两个问题

  1. 心跳是用来保证你在线的。
  2. 断线重连,是保证异常情况的。

你可以连我的websocket服务器测试呀。

image.png


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...