JavaScript WebSocket实现长连接通信连接重连

JavaScript-JS依靠WebSoket也可以像其他语言一样能够实现通信代码,不过使用的时候需要注意检查连接断开的情况。最基本的必须保证IP和端口都可以访问。

目录

WebSocket代码及测试

调用初始化代码

通信示例代码

测试效果

WebSocket连接关闭重连处理

连接断开问题

代码实现重连

重连效果


WebSocket代码及测试

调用初始化代码

 CvNetVideo.Websocket = new WebSocket('ws://' + websocetHost + ":" + websocketPort);
 CvNetVideo.WebsocketCallbackLoader = new WebsocketCallbackLoader();
 CvNetVideo.WebsocketCallbackLoader.connect(CvNetVideo.Websocket);

通信示例代码

/*
 * WebsocketCallback Loader
*/
import JT1078 from '../JX/JTT1078';

class WebsocketCallbackLoader {

    constructor() {
        this.websocket = undefined;
        this.onCallback = undefined;
        this.sendMessage = this.sendMessage;
        this.medisPackageAnalysis = new JT1078.MedisPackageAnalysis();
        this.splitData = new JT1078.SplitData();
        this.checkHelper = new JT1078.CheckHelper();
        //分包缓存数据 按SIM做key
        this.AllSimPackData = {};
    }

    connect(websocket) {
        this.websocket = websocket;
        this.websocket.onopen = this.openSocket.bind(this);
        this.websocket.onclose = this.closeSocket.bind(this);
        this.websocket.binaryType = 'arraybuffer';
        this.websocket.onmessage = this.receiveSocketMessage.bind(this);
    }

    closeSocket(e) {
        console.log('Websocket808 Disconnected!');
    }

    openSocket() {
        console.log('Websocket808 Open!');
    }

    receiveSocketMessage(event) {
        let data = new Uint8Array(event.data);
        this.splitData.SplitDataBy7E(data, 18, data.byteLength - 18, (bGps) => {
            if (bGps.length > 11 && this.checkHelper.CheckXOR(bGps, 0, bGps.length - 1) === bGps[bGps.length - 1])//效验通过
            {
                this.JX808DataPD(new Uint8Array(bGps));
            }
        });
    }
    JX808DataPD(bGps) {
        let head = new JT1078.JTHeader();
        head.FillByBinary(bGps, 0);

        if (head.PackInfo) {
            var sid = JT1078.GetFirstSerialNumber(head);
            let AllPackData = AllSimPackData[head.Sim];
            if (!AllPackData) {
                AllPackData = {};
                AllSimPackData[head.Sim] = AllPackData;
            }

            var pd = AllPackData[sid];
            if (pd) {
                if (!pd.PackData[head.PackInfo.Index]) {
                    pd.PackData.Count += 1;
                }
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.LastRTime = DateTime.Now;
                if (this.CheckPackByPD(pd))
                    AllPackData[sid] = null;
            }
            else {
                pd = {};
                pd.PackData = {};
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.PackData.Count = 1;
                pd.Head = new JT1078.JTHeader(head.MsgId, head.Sub, head.DataEncryptType, head.MsgLen, head.Sim, sid)
                pd.Head.PackInfo = new JT1078.JTPackageInfo(1, head.PackInfo.Sum);
                pd.StartTime = pd.LastRTime = DateTime.Now;
                AllPackData[sid] = pd;
            }

        } else {
            this.JX808Data(head, JT1078.GetMsbBody(head, bGps));
        }
    }
    CheckPackByPD(pd) {
        if (pd.PackData.Count === pd.Head.PackInfo.Sum)//判断数据包数和总包数是否相等
        {
            let tmpbuf = new Uint8Array();
            let index = 0;
            for (var i = 0; i < pd.Head.PackInfo.Sum; i++) {
                tmpbuf.set(pd.PackData[i], index);
                index += pd.PackData[i].byteLength;
            }
            //解析失败时返回true防止一直解析此错误数据
            try {
                this.JX808Data(pd.Head, tmpbuf);
            }
            catch (ex)
            {
                console.error(ex);
                return true;
            }
            return true;
        }
        return false;
    }
    JX808Data(head, bts) {
        switch (head.MsgId) {

            case 0x1205://终端上传音视频资源列表数据格式
                var videolist = new JT1078.JTVideoListInfo();
                videolist.FillByBinary(bts, 0);
                this.onCallback(videolist);
                break;
            case 0x1206://终端上传FTP完成通知
                break;
            default:
        }
    }

    sendMessage(data, callback) {
        this.onCallback = callback;
        switch (this.websocket.readyState) {
            case 0:
                console.log("Websocket808 readyState=CONNECTING");
                break;
            case 1:
                this.websocket.send(data);
                break;
            case 2:
                console.log("Websocket808 readyState=CLOSING");
                break;
            case 3:
                console.log("Websocket808 readyState=CLOSED");
                break;

        }

    }

}

export default WebsocketCallbackLoader;  

测试效果

WebSocket连接关闭重连处理

连接断开问题

代码实现重连

改造一下调用代码和发送消息代码:

   static initWebsocket(websocetHost, websocketPort) {
        CvNetVideo.WebsocketCallbackLoader = new WebsocketCallbackLoader(websocetHost, websocketPort);
        CvNetVideo.WebsocketCallbackLoader.connect();
    }
/*
 * WebsocketCallback Loader
*/
import JT1078 from '../JX/JTT1078';
import { setTimeout } from 'timers';

class WebsocketCallbackLoader {

    constructor(host, port) {
        this.host = host;
        this.port = port;
        this.websocket = undefined;
        this.onCallback = undefined;
        this.sendMessage = this.sendMessage;
        this.medisPackageAnalysis = new JT1078.MedisPackageAnalysis();
        this.splitData = new JT1078.SplitData();
        this.checkHelper = new JT1078.CheckHelper();
        //分包缓存数据 按SIM做key
        this.AllSimPackData = {};
    }

    connect() {
        var url = "ws://" + this.host + ":" + this.port;
        console.log("Websocket808 WebSocket connect ..." + url);
        this.websocket = new WebSocket(url);
        this.websocket.onopen = this.openSocket.bind(this);
        this.websocket.onclose = this.closeSocket.bind(this);
        this.websocket.binaryType = 'arraybuffer';
        this.websocket.onmessage = this.receiveSocketMessage.bind(this);
    }

    closeSocket(e) {
        console.log('Websocket808 Disconnected!');
    }

    openSocket() {
        console.log('Websocket808 Open!');
    }

    receiveSocketMessage(event) {
        let data = new Uint8Array(event.data);
        this.splitData.SplitDataBy7E(data, 18, data.byteLength - 18, (bGps) => {
            if (bGps.length > 11 && this.checkHelper.CheckXOR(bGps, 0, bGps.length - 1) === bGps[bGps.length - 1])//效验通过
            {
                this.JX808DataPD(new Uint8Array(bGps));
            }
        });
    }
    JX808DataPD(bGps) {
        let head = new JT1078.JTHeader();
        head.FillByBinary(bGps, 0);

        if (head.PackInfo) {
            var sid = JT1078.GetFirstSerialNumber(head);
            let AllPackData = AllSimPackData[head.Sim];
            if (!AllPackData) {
                AllPackData = {};
                AllSimPackData[head.Sim] = AllPackData;
            }

            var pd = AllPackData[sid];
            if (pd) {
                if (!pd.PackData[head.PackInfo.Index]) {
                    pd.PackData.Count += 1;
                }
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.LastRTime = DateTime.Now;
                if (this.CheckPackByPD(pd))
                    AllPackData[sid] = null;
            }
            else {
                pd = {};
                pd.PackData = {};
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.PackData.Count = 1;
                pd.Head = new JT1078.JTHeader(head.MsgId, head.Sub, head.DataEncryptType, head.MsgLen, head.Sim, sid)
                pd.Head.PackInfo = new JT1078.JTPackageInfo(1, head.PackInfo.Sum);
                pd.StartTime = pd.LastRTime = DateTime.Now;
                AllPackData[sid] = pd;
            }

        } else {
            this.JX808Data(head, JT1078.GetMsbBody(head, bGps));
        }
    }
    CheckPackByPD(pd) {
        if (pd.PackData.Count === pd.Head.PackInfo.Sum)//判断数据包数和总包数是否相等
        {
            let tmpbuf = new Uint8Array();
            let index = 0;
            for (var i = 0; i < pd.Head.PackInfo.Sum; i++) {
                tmpbuf.set(pd.PackData[i], index);
                index += pd.PackData[i].byteLength;
            }
            //解析失败时返回true防止一直解析此错误数据
            try {
                this.JX808Data(pd.Head, tmpbuf);
            }
            catch (ex)
            {
                console.error(ex);
                return true;
            }
            return true;
        }
        return false;
    }
    JX808Data(head, bts) {
        switch (head.MsgId) {

            case 0x1205://终端上传音视频资源列表数据格式
                var videolist = new JT1078.JTVideoListInfo();
                videolist.FillByBinary(bts, 0);
                this.onCallback(videolist);
                break;
            case 0x1206://终端上传FTP完成通知
                break;
            default:
        }
    }

    printState() {
        switch (this.websocket.readyState) {
            case 0:
                console.log("Websocket808 readyState=CONNECTING");
                break;
            case 1:
                console.log("Websocket808 readyState=OPEN");
                break;
            case 2:
                console.log("Websocket808 readyState=CLOSING");
                break;
            case 3:
                console.log("Websocket808 readyState=CLOSED");
                break;
        }
    }

    sendData(data)
    {
        this.websocket.send(data);
    }

    sendMessage(data, callback) {
        this.onCallback = callback;
        this.printState();
        if (this.websocket.readyState === 0) {
            setTimeout(() => {
                this.sendData(data);
            }, 3000);
        } else if (this.websocket.readyState === 2 || this.websocket.readyState === 3) {
            this.connect();
            setTimeout(() => {
                this.printState();
                this.sendData(data);
            }, 3000);
        } else {
            this.sendData(data);
        }

    }

}

export default WebsocketCallbackLoader;  

重连效果

 下面是连接断开后重连效果:

注意:重连是异步调用的,使用setTimeout(func,ms) 调用,因为连接创建需要时间,直接连很有可能正在连接。

使用队列处理连接失败数据

/*
 * WebsocketCallback Loader
*/
import JT1078 from '../JX/JTT1078';
import Queue from '../utils/queue';

class WebsocketCallbackLoader{

    constructor(host, port) {
        this.host = host;
        this.port = port;
        this.websocket = undefined;
        this.medisPackageAnalysis = new JT1078.MedisPackageAnalysis();
        this.splitData = new JT1078.SplitData();
        this.checkHelper = new JT1078.CheckHelper();
        //分包缓存数据 按SIM做key
        this.AllSimPackData = {};
        this.sendCache = new Queue();
        this.onCallback = {};
    }

    connect() {
        var url = "ws://" + this.host + ":" + this.port;
        this.websocket = new WebSocket(url);
        this.websocket.onopen = this.openSocket.bind(this);
        this.websocket.onclose = this.closeSocket.bind(this);
        this.websocket.binaryType = 'arraybuffer';
        this.websocket.onmessage = this.receiveSocketMessage.bind(this);
    }

    closeSocket(e) {
        console.log('Websocket808 Disconnected!');
    }

    openSocket() {
        console.log('Websocket808 Open!');
        while (this.sendCache.size() > 0) {
            this.sendData(this.sendCache.dequeue());
        }
    }

    receiveSocketMessage(event) {
        let data = new Uint8Array(event.data);
        this.splitData.SplitDataBy7E(data, 18, data.byteLength - 18, (bGps) => {
            if (bGps.length > 11 && this.checkHelper.CheckXOR(bGps, 0, bGps.length - 1) === bGps[bGps.length - 1])//效验通过
            {
                this.JX808DataPD(new Uint8Array(bGps));
            }
        });
    }
    JX808DataPD(bGps) {
        let head = new JT1078.JTHeader();
        head.FillByBinary(bGps, 0);

        if (head.PackInfo) {
            var sid = JT1078.GetFirstSerialNumber(head);
            let AllPackData = this.AllSimPackData[head.Sim];
            if (!AllPackData) {
                AllPackData = {};
                this.AllSimPackData[head.Sim] = AllPackData;
            }

            var pd = AllPackData[sid];
            if (pd) {  
                if (!pd.PackData[head.PackInfo.Index]) {
                    pd.PackData.Count += 1;
                    pd.PackData.totalLength += head.MsgLen;
                }
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.LastRTime = new Date();
                if (this.CheckPackByPD(pd))
                    AllPackData[sid] = null;
            }
            else {
                pd = {};
                pd.PackData = {};
                pd.PackData[head.PackInfo.Index] = JT1078.GetMsbBody(head, bGps);
                pd.PackData.Count = 1;
                pd.PackData.totalLength = head.MsgLen;
                pd.Head = new JT1078.JTHeader(head.MsgId, head.Sub, head.DataEncryptType, head.MsgLen, head.Sim, sid);
                pd.Head.PackInfo = new JT1078.JTPackageInfo(1, head.PackInfo.Sum);
                pd.StartTime = pd.LastRTime = new Date();
                AllPackData[sid] = pd;
            }

        } else {
            this.JX808Data(head, JT1078.GetMsbBody(head, bGps));
        }
    }
    CheckPackByPD(pd) {
        if (pd.PackData.Count === pd.Head.PackInfo.Sum)//判断数据包数和总包数是否相等
        {
            let tmpbuf = new Uint8Array(pd.PackData.totalLength);
            let index = 0;
            for (var i = 1; i <= pd.Head.PackInfo.Sum; i++) {
                tmpbuf.set(pd.PackData[i], index);
                index += pd.PackData[i].byteLength;
            }
            //解析失败时返回true防止一直解析此错误数据
            try {
                this.JX808Data(pd.Head, tmpbuf);
            }
            catch (ex) {
                console.error(ex);
                return true;
            }
            return true;
        }
        return false;
    }
    JX808Data(head, bts) {
        switch (head.MsgId) {

            case 0x1205://终端上传音视频资源列表数据格式
                var videolist = new JT1078.JTVideoListInfo();
                videolist.FillByBinary(bts, 0);
                this.onCallback[0x1205](videolist);
                break;
            case 0x1206://终端上传FTP完成通知
                var fileUploadEndInform = new JT1078.JTVideoFileUploadEndInform();
                fileUploadEndInform.FillByBinary(bts, 0);
                this.onCallback[0x1206](fileUploadEndInform);
                break;
            default:
        }
    }

    printState() {
        switch (this.websocket.readyState) {
            case 0:
                console.log("Websocket808 readyState=CONNECTING");
                break;
            case 1:
                console.log("Websocket808 readyState=OPEN");
                break;
            case 2:
                console.log("Websocket808 readyState=CLOSING");
                break;
            case 3:
                console.log("Websocket808 readyState=CLOSED");
                break;
        }
    }

    sendData(data)
    {
        this.websocket.send(data);
    }

    sendMessage(data, callback, id) {

        this.onCallback[id] = callback;
        if (this.websocket.readyState === 0) {
            this.sendCache.enqueue(data);
        } else if (this.websocket.readyState === 2 || this.websocket.readyState === 3) {
            this.printState();
            this.sendCache.enqueue(data);
            this.connect();
        } else {
            this.sendData(data);
        }

    }

}

export default WebsocketCallbackLoader;  

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用 Vue.js 和 WebSocket 实现页面实时刷新。 首先,在你的 Vue 组件中创建一个 WebSocket 对象: ``` let socket = new WebSocket('ws://your-websocket-server'); ``` 然后,添加一个监听器来处理服务器发送的消息: ``` socket.onmessage = function (event) { // 处理服务器发送的消息 } ``` 当你的 Vue 组件中的数据发生变化时,你可以使用 WebSocket 向服务器发送消息: ``` socket.send(JSON.stringify({ // 发送的数据 })); ``` 最后,在组件销毁时,记得关闭 WebSocket 连接: ``` beforeDestroy() { socket.close(); } ``` 希望这些信息能帮到你! ### 回答2: Vue WebSocket 实现页面实时刷新连接的过程如下: 首先,需要在Vue项目中安装WebSocket库。可以使用npm安装vue-native-websocket库,该库提供了适用于Vue的WebSocket模块。通过运行`npm install vue-native-websocket`命令进行安装。 安装完成后,在Vue项目的入口文件main.js中导入WebSocket库。通过以下代码实现: ```javascript import VueNativeSock from 'vue-native-websocket' Vue.use(VueNativeSock, 'ws://localhost:8080', { reconnection: true, // 是否自动连接 reconnectionAttempts: 5, // 连接次数 reconnectionDelay: 3000, // 连接延迟时间,单位ms }) ``` 这里通过Vue.use()方法将WebSocket库注册到Vue应用中,并指定连接的URL以及一些配置项,如是否自动连接连接次数和延迟时间。 接下来,在Vue组件中使用WebSocket。可以在created()生命周期钩子函数中创建WebSocket连接。可以通过以下代码实现: ```javascript export default { created() { this.$options.sockets.onmessage = (data) => { // 接收到消息时的处理逻辑 // 刷新页面或做其他操作 } }, // ... } ``` 这里通过设置this.$options.sockets.onmessage回调函数,当接收到WebSocket服务器发送的消息时,该函数中的逻辑将被执行。在该函数中可以实现页面的实时刷新或其他操作。 最后,需要在WebSocket服务器端实现消息的发送。根据具体的服务器端实现方式,可以使用相应语言和框架提供的WebSocket库,将消息发送给连接的客户端。 总结起来,Vue WebSocket 实现页面实时刷新连接的过程包括:安装WebSocket库、在入口文件中注册WebSocket模块、在组件中使用WebSocket并处理接收到的消息、在服务器端实现消息的发送。通过这些步骤,便可以在Vue应用中实现WebSocket连接,并根据接收到的消息实现页面的实时刷新。 ### 回答3: Vue WebSocket 可以实现页面实时刷新连接,具体步骤如下: 1. 首先,在 Vue 项目中安装 WebSocket 插件。 2. 在需要实时刷新的页面或组件中,引入 WebSocket 并创建连接。 3. 创建 WebSocket 连接后,可以监听连接的状态,比如打开、关闭、错误等。 4. 使用 WebSocket 的 onmessage 事件监听服务器发送的消息,一旦收到消息,即可触发页面或组件的刷新操作。 5. 可以通过 WebSocket 的 send 方法向服务器发送消息,实现与服务器的双向通信。 6. 在页面或组件销毁时,记得关闭 WebSocket 连接以避免资源浪费。 总结起来,Vue WebSocket 实现页面实时刷新连接的步骤包括安装插件、创建连接、监听连接状态、监听服务器发送消息、发送消息以及关闭连接。这样可以实现页面与服务器的实时双向通信,达到页面实时刷新的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值