WebSocket is already in CLOSING or CLOSED state. 报错信息的解决方案

今天遇到这样一些错误,中文的意思是 websocket 已经关闭了

简单查了一些资料分析如下

为什么会断开

WebSocket断开的原因有很多,服务端客户端主动断开(服务器宕机服务停止,客户端关闭网页),网络不稳定被动断开(物理层断开,或者网络底层数据错误)

我们可以将错误日志打印出来

ws.onclose = function (e) {logger.error('websocket 断开');logger.info(e.code + ' ' + e.reason + ' ' + e.wasClean);
}

WS 断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WS 的客户端. 它在 WS 对象的 onclose 事件监听器中使用。

CloseEvent有三个字段需要注意, 通过分析这三个字段,一般就可以找到断开原因

  • CloseEvent.code: code是错误码,number
  • CloseEvent.reason: reason是断开原因,string
  • CloseEvent.wasClean: wasClean表示是否正常断开,boolean,异常断开时,该值为false

解决方案1

监测到断开后,客户端重新发出连接

如果还是没有链接成功,界面提示用户,由于网络问题,需要重新打开浏览器,或者请检查网络

例如:这是服务端 server 代码

const WebSocket = require('ws');
const ws = new WebSocket.Server({ server });ws.on('connection', function connection(socket) {// 当接受消息,打印日志socket.on('message', function incoming(data) {console.log('Incoming data ', data);});
});

这是客户端 client 代码

// 创建 WS 链接
const socket = new WebSocket('ws://localhost:8080'); // 监听连接事件
socket.addEventListener('open', function(event) {console.log("Connected to server");
});// 监听消息事件
socket.addEventListener('message', function(event) {console.log('Message from server ', event);
});// 发送数据
var data = {name: 'admin'};
socket.send(JSON.stringify(data));

可以在发送数据前,检查一下是否链接

function isOpen(ws) {return ws.readyState === ws.OPEN
}if (isOpen(socket)) {var data = {name: 'admin'};socket.send(JSON.stringify(data));
} else {logger.info('web socket is closing, reconnecting');
}

解决方案2

这是参考另一个思路,设置心跳监测连接,断线重连(借鉴 https://www.cnblogs.com/gxp69/p/11736749.html 的思路)

var lockReconnect = false;  // 避免ws重复连接
var ws = null;          // 判断当前浏览器是否支持WebSocket
var wsUrl = socketUrl;// 连接ws
createWebSocket(wsUrl);/*** 创建 WS 实例* @param {string} url ws的URL*/
function createWebSocket(url) {try {if ('WebSocket' in window) {ws = new WebSocket(url);}initEventHandle();} catch(e) {reconnect(url);console.log(e);}
}/*** 初始化事件处理*/
function initEventHandle() {ws.onclose = function () {reconnect(wsUrl);console.log("WS 连接关闭!" + new Date().toLocaleString());};ws.onerror = function () {reconnect(wsUrl);console.log("WS 连接错误!");};ws.onopen = function () {//心跳检测重置heartCheck.reset().start();console.log("WS 连接成功!" + new Date().toLocaleString());};ws.onmessage = function (event) {//如果获取到消息,心跳检测重置//拿到任何消息都说明当前连接是正常的heartCheck.reset().start();console.log("WS 收到消息啦:" +event.data);if (event.data != 'pong') {let data = JSON.parse(event.data);}};
}// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {ws.close();
}/*** 重连* @param {string} url ws的URL* @returns null*/
function reconnect(url) {if (lockReconnect) return;lockReconnect = true;// 没连接上,会一直重连,设置延迟 2s 避免连接频繁setTimeout(function () {createWebSocket(url);lockReconnect = false;}, 2000);
}// 心跳检测
var heartCheck = {timeout: 1000,timeoutObj: null,serverTimeoutObj: null,reset: function() {clearTimeout(this.timeoutObj);clearTimeout(this.serverTimeoutObj);return this;},start: function() {var self = this;this.timeoutObj = setTimeout(function() {//这里发送一个心跳,后端收到后,返回一个心跳消息,//onmessage拿到返回的心跳就说明连接正常ws.send("ping");console.log("ping!")//如果超过一定时间还没重置,说明后端主动断开了self.serverTimeoutObj = setTimeout(function() {//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次ws.close();}, self.timeout)}, this.timeout)}
}

参考链接

Stack Overflow

心跳监测介绍

CSDN

CSDN

WebSocket is already in CLOSING or CLOSED state相关推荐

  1. WebSocket is already in CLOSING or CLOSED state解决方案

    使用flask + websocket来进行前后端交互的项目 前端发送send的时候,websocket一连接就中断,测试了心跳设置相应时间等各种方法,都没用,最后发现原来是flask的版本太高导致和 ...

  2. WPF window窗体的关闭事件Closing 和Closed

    当窗口关闭时,它会引发两个事件:Closing 和 Closed. Closing 在窗口关闭之前引发,它提供一种机制,可以通过这种机制来阻止窗口关闭. 系统会向Closing 事件处理程序传递一个 ...

  3. C# 坦克游戏大战中学习相关类(Closing与Closed区别)

     C# 坦克游戏大战,窗体Form中Closing代码如下: private void Form1_FormClosing(object sender, FormClosingEventArgs e) ...

  4. Websocket跨域访问

    WebSocket 是 HTML5 开始提供的⼀种在单个 TCP 连接上进⾏全双⼯通讯的协议,可以实现跨域访问. websocket安装命令 npm i ws -S 服务器端: let WebServ ...

  5. 蚂蚁集团-数字金融线-体验技术部前端一面面经

    声明一下:这篇文章是我原著,原发布于牛客网,对,那个叫德布罗煜的就是我.球球各路卖资料的,别盗了,一个破面经也偷啊? 面试官 19:00 打了个电话过来,说往我邮箱里发了个链接,让我先做一个小时的笔试 ...

  6. c++ websocket 客户端

    本次创建一个c++ 的websocket客户端,不依赖于其他库 头文件 #ifndef _WS_CLIENT_H #define _WS_CLIENT_H#ifdef _WIN32 #define _ ...

  7. flask+vue+websocket+neo4j+torch模型项目常见报错

    一.vue和flask部分 webpack-dev-server 不是内部或外部命令,也不是可运行的程序 - 删除node_modules 和 npm-shrinkwrap.json - npm sh ...

  8. WebSocket 详解

    WebSocket 出现前 构建网络应用的过程中,我们经常需要与服务器进行持续的通讯以保持双方信息的同步.通常这种持久通讯在不刷新页面的情况下进行,消耗一定的内存资源常驻后台,并且对于用户不可见.在 ...

  9. HTML5中的webSocket、ajax、http

    本文原链接:https://cloud.tencent.com/developer/article/1115496 https://cloud.tencent.com/developer/articl ...

  10. WebSocket实战

    前言 互联网发展到现在,早已超越了原始的初衷,人类从来没有像现在这样依赖过他:也正是这种依赖,促进了互联网技术的飞速发展.而终端设备的创新与发展,更加速了互联网的进化: HTTP/1.1规范发布于19 ...

最新文章

  1. java反射的性能_java反射的性能问题
  2. tp5 if 如果有html判断,tp5条件判断,in,notin,between,if等
  3. 全国计算机等级考试题库二级C操作题100套(第55套)
  4. 如何正确实现 Java 中的 HashCode
  5. 【狂神说】分析前后端分离开源项目?
  6. ThinkCMF是一款支持Swoole的开源内容管理框架,基于ThinkPHP开发,同时支持PHP-FPM和Swoole双模式,让WEB开发更快!
  7. 读取properties资源文件中的参数
  8. 封装axios统一请求
  9. c++语言中的循环语句有,C++语言中的循环语句
  10. 08-09 性能测试--CPU分析
  11. php堆栈溢出,php - 警告:php_eval() - 堆栈内存溢出
  12. 【转载】动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)...
  13. MCMC算法大统一: Involutive MCMC
  14. 高等数学-学习笔记-闻彬
  15. smart检测指标详解
  16. 嵌入式cc2530单片机ZigBee-流水灯的实验
  17. word 方框内打勾√或打叉×
  18. 如何屏蔽知乎网页中的热搜
  19. 可编辑PDF使用pdfplumber无法抽取出文本和表格
  20. Android开发必会技术!Flutter中网络图片加载和缓存源码分析,完整PDF

热门文章

  1. 99刀299刀 开发者账户 区别
  2. 开机预读快还是不预读快_启用预读为网页浏览提速
  3. 皮影机器人ppt_机器人皮影戏装置的制作方法
  4. 如何解决fillRect方法画矩形变形的问题?
  5. 微信小程序,Python爬虫抓包采集实战,采集某成考题库小程序
  6. 22:紧急措施http://noi.openjudge.cn/ch0107/22/
  7. python使用pika库调用rabbitmq的交换机模式
  8. 一场分销裂变活动,不止是发发朋友圈这么简单
  9. SPDK/NVMe存储技术分析之用户态ibv_post_send()源码分析(一)
  10. ghost linux 黑屏,Ghost 与 Linux 的兼容性