本文主要讲的是如果设计websocket心跳已经需要考虑哪些问题。

前言

在使用websocket的过程中,有时候会遇到客户端网络关闭的情况,而这时候在服务端并没有触发onclose事件。这样会:

多余的连接

服务端会继续给客户端发数据,这些数据会丢失

所以就需要一种机制来检测客户端和服务端是否处于正常连接的状态。这就是websocket心跳,这个名字非常生动形象,还有心跳说明还活着(保持正常连接),没有心跳说明已经挂掉了(连接断开了)。

要解决的问题

我的代码主要解决了以下几个问题。

连接上之后,每秒发送一个心跳,服务器同样返回一个心跳,用来表示服务器没挂。

断线重连(我们测试的环境是断开网络连接),断开网络后,心跳包无法发送出去,所以如果当前时间距离上次成功心跳的时间超过20秒,说明连接已经出现问题了,此时需要关闭连接。

第一次关闭连接时websocket会尝试重连,设置了一个时间期限,10秒。10秒内如果能连上(恢复网络连接)就可以继续收发消息,连不上就关闭了,并且不会重连。

30秒内收不到服务器消息(心跳每秒发送),我就认为服务器已经挂了,就会调用close事件,然后进入第3步。

需要什么

开始考虑得不周到,命名不规范。

一个定时器ws.keepAliveTimer,用来每秒发送一次心跳。

上次心跳成功的时间ws.last_health_time以及当前时间let time = new Date().getTime();。

断开连接(ws.close())时的时间reconnect,因为在close事件发生后需要重连10秒。

是否已经重连过reconnectMark。

断开连接(ws.close())时需要保存ws对象tempWs。我曾试图ws = { ...ws }发现会丢失绑定的事件。

一个定时时间为30秒的setTimeout定时器ws.receiveMessageTimer,用来表示服务器是否在30秒内返回了消息。

代码部分

我是在react中使用websocket心跳的。当用户登录时我会建立websocket连接。由于使用了redux,所以该部分代码放在componentWillReceiveProps中。

componentWillReceiveProps(nextProps) {

if(nextProps.isLogin && !this.state.notificationSocket) { // 用户登录了并且没有连接过websocket

let ws = new WebSocket(`${chatUrl}/${nextProps.userId}`);

ws.last_health_time = -1; // 上一次心跳时间

ws.keepalive = function() {

let time = new Date().getTime();

if(ws.last_health_time !== -1 && time - ws.last_health_time > 20000) { // 不是刚开始连接并且20s

ws.close()

} else {

// 如果断网了,ws.send会无法发送消息出去。ws.bufferedAmount不会为0。

if(ws.bufferedAmount === 0 && ws.readyState === 1) {

ws.send('h&b');

ws.last_health_time = time;

}

}

}

if(ws) {

let reconnect = 0; //重连的时间

let reconnectMark = false; //是否重连过

this.setState({

notificationSocket: true

})

ws.onopen = () => {

reconnect = 0;

reconnectMark = false;

ws.receiveMessageTimer = setTimeout(() => { ws.close(); }, 30000); // 30s没收到信息,代表服务器出问题了,关闭连接。如果收到消息了,重置该定时器。 if(ws.readyState === 1) { // 为1表示连接处于open状态 ws.keepAliveTimer = setInterval(() => { ws.keepalive(); }, 1000) } } ws.onerror = () => {

console.error('onerror')

}

ws.onmessage = (msg) => {

/* 这一注释部分是我的业务逻辑代码,大家可以忽略

msg = JSON.parse(msg.data);

let chatObj = JSON.parse(localStorage.getItem(CHATOBJECT)) || {};

if(msg && msg.senderUserId && !chatObj[msg.senderUserId]) chatObj[msg.senderUserId] = [];

if(msg.content !== 'h&b') {

if(msg.chat === true) { // 聊天

// chatObj[msg.senderUserId] = [

{msg.content}

, ...chatObj[msg.senderUserId]]

chatObj[msg.senderUserId].unshift(msg.content);

WindowNotificationUtils.notice(msg.title, msg.content, () => { const { history } = this.props; history.replace({ pathname: '/sendNotice', search: `?senderUserId=${msg.senderUserId}` // 为什么放在url,因为刷新页面数据不会掉 }); }) localStorage.setItem(CHATOBJECT, JSON.stringify(chatObj)); this.props.dispatch({ type: UPDATE_CHAT }) } else { // 通知 WindowNotificationUtils.notice(msg.title, msg.content); } } */ // 收到消息,重置定时器 clearTimeout(ws.receiveMessageTimer); ws.receiveMessageTimer = setTimeout(() => { ws.close(); }, 30000); // 30s没收到信息,代表服务器出问题了,关闭连接。 } ws.onclose = () => {

clearTimeout(ws.receiveMessageTimer);

clearInterval(ws.keepAliveTimer);

if(!reconnectMark) { // 如果没有重连过,进行重连。

reconnect = new Date().getTime();

reconnectMark = true;

}

let tempWs = ws; // 保存ws对象

if(new Date().getTime() - reconnect >= 10000) { // 10秒中重连,连不上就不连了

ws.close();

} else {

ws = new WebSocket(`${chatUrl}/${nextProps.userId}`);

ws.onopen = tempWs.onopen;

ws.onmessage = tempWs.onmessage;

ws.onerror = tempWs.onerror;

ws.onclose = tempWs.onclose;

ws.keepalive = tempWs.keepalive;

ws.last_health_time = -1;

}

}

}

}

}

以上就是websocket心跳的全部实现。看到断开网络后然后再脸上网络websocket又连上了,那一刻心里很喜悦。如果有什么问题,欢迎大家和我交流。

邮箱: 1227620310@qq.com

websocket心跳链接代码_websocket心跳的实现(包括全部代码)相关推荐

  1. socket心跳机制图片_WebSocket心跳检测和重连机制

    1. 心跳重连原由 心跳和重连的目的用一句话概括就是客户端和服务端保证彼此还活着,避免丢包发生. websocket连接断开有以下两种情况: 前端断开 在使用websocket过程中,可能会出现网络断 ...

  2. 低代码发展专访系列之八:低代码平台能够打破企业「应用孤岛」现象吗?

    话题:低代码发展系列专访 前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CSDN随后展开低代码 ...

  3. 低代码发展系列专访之三:低代码平台会成为企业数字化基础设施么?

    话题: 低代码专访 前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CSDN随后展开低代码平台产 ...

  4. 低代码发展专访系列之七:低代码的火爆需要不一样的声音么?

    编辑 | 曹芊芊 话题:低代码发展系列专访 前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CS ...

  5. 低代码发展专访系列之六:低代码平台能解决业务重构的问题么?

    编辑 | 曹芊芊 话题:低代码发展系列专访 前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CS ...

  6. 低代码发展系列专访之五:低代码的最大价值点是“技术平民化”吗?

    话题: 低代码专访 编辑 | LLBin 前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CSD ...

  7. 低代码发展专访系列之四:低代码平台会带动企业的组织变革吗?

    前言:2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CSDN随后展开低代码平台产品系列活动,包括低代 ...

  8. 低代码发展专访系列之一:低代码平台产品的使用者都是谁?

    2019年开始,低代码爆火.有人认为它是第四代编程语言,有人认为它是开发模式的颠覆,也有人认为是企业管理模式的变革--有很多声音,社区讨论很热烈.CSDN随后展开低代码平台产品系列活动,包括低代码开发 ...

  9. websocket心跳链接代码_WebSocket原理与实践(五)--心跳及重连机制

    在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失.所以就需要 ...

最新文章

  1. vue2.0 -- watch监听
  2. 绝对强大的三个LINUX指令: AR, NM, OBJDUMP
  3. ActiveMQ消息中间件的作用以及应用场景
  4. Struts2_1_基础案例_配置文件详解_动作类
  5. LeetCode 816. 模糊坐标
  6. Xen虚拟机两大迁移方法详解
  7. python闹钟界面程序_「Python编程」自由管理时间之编写一个小闹钟起床
  8. php cli获取参数,php cli模式下获取参数的方法
  9. 51单片机 | 基于I2C总线的秒表模拟应用
  10. XP共享拒绝访问,全面解决
  11. 使scp不用输入密码
  12. 【光学】基于matlab GUI(杨氏双缝+劈尖)干涉+(单缝+多缝+圆孔+矩孔)衍射仿真【含Matlab源码 878期】
  13. 用python自制一个简单的答题程序
  14. opencv之图像二值化处理
  15. 07-新闻发布系统数据库-新闻信息数据操作
  16. CAN总线学习:zlg关于can帖子汇总
  17. 百度2017春招-买帽子
  18. 国家取消职称英语与计算机,全国职称英语考试取消
  19. UML中各图形或图标表示的意思
  20. Webpack入门教程十八

热门文章

  1. 盒模型、盒子模型、框模型(box model)
  2. 129:Krypton Factor
  3. 搭建一个AdGuard Home私人DNS
  4. html案例:模拟一个很简单的聊天框
  5. eprime提示计算机内存不足,请各位前辈看看这是否是内存不足的原因导致出错 - 第一原理 - 小木虫 - 学术 科研 互动社区...
  6. 荣耀秋招嵌入式正式批
  7. MATLAB R2018b学习笔记(3)
  8. 2017 开源软件排行_震撼2017年的十大开源法律故事
  9. 走近Dubbo(附Dubbo思维导图)
  10. KSM,UKSM,PKSM(2/2)