服务端代码

websocket.js

'use strict'

const WebSocket = require('ws');
const connections = new Map();
const Constr = function(port) {
const self = this;
self.webSocket = new WebSocket.Server({ port: port });
};
Constr.prototype.connect = function() {
const self = this;
self.webSocket.on('connection', function connection(ws) {
try {
ws.on('message', function incoming(message) {
try {
if (connections.size > 2000) {
ws.send(1);
ws.close();
return;
}
ws.send(0);
if (connections.get(message) && connections.get(message).ws.readyState == WebSocket.OPEN) {
connections.get(message).date = Date.now();
connections.get(message).ws.isAlive = true;
console.log(message + ':上次心跳时间' + connections.get(message).date);
return;
}
connections.set(message, {
ws: ws,
date: Date.now(),
});
console.log('客户端imei:' + message + '握手、心跳成功!时间:' + connections.get(message).date);
ws.on('close', function close() { console.log('连接关闭 ' + message)
// ws.reconnect();
if (connections.get(message)) {
connections.delete(message);
}
ws.close();
});
ws.on('error', function close() {
console.error(message + ':出现错误!强制下线');
connections.get(message)
.ws
.close();
});
// 服务器接受pong消息++huanglong,确定mtk接受ping,并pong服务器后打开
// ws.on('pong', function() {
// connections.get(message).date = Date.now();
// connections.get(message).ws.isAlive = true;
// console.log('上次接收pong时间' + connections.get(message).date);
// });
} catch (e) {
console.error('on message error:', e);
}
});
}catch (e) {
console.error('on connection error:', e);
}
});
self.webSocket.on('error',function(){
console.log('error');
});
};
Constr.prototype.send = function(obj) {
console.log('下推消息:' + JSON.stringify(obj));
const imeiArray = obj.imei.split(',');
for (let i = 0; i < imeiArray.length; i++) {
try {
if (connections.get(imeiArray[i]) && connections.get(imeiArray[i]).ws.readyState === WebSocket.OPEN) {
console.log(imeiArray[i] + ':连接状态' + connections.get(imeiArray[i]).ws.readyState);
connections.get(imeiArray[i]).ws.send(obj.str);
} else {
console.log('imei:' + imeiArray[i] + 'socket关闭!');
connections.delete(imeiArray[i]);
}
} catch (e) {
console.log('发送消息发生严重错误!imei:' + imeiArray[i]);
}
}
}; Constr.prototype.heartbeatCheck = function() {
console.log('心跳检查:当前握手连接数为' + connections.size + '客户端:' + connections.keys().toString());
if (connections.size === 0) {
return;
}
connections.forEach(function (value, key) {
if (Date.now() - value.date > 60000) {
connections.delete(key);
try {
value.ws.close();
}catch (e) {
console.error('close error', e);
}
}
// ++huanglong,暂时关闭ping机制,确定mtk接受ping,并pong服务器后打开
// if (value.ws.isAlive === false) return value.ws.terminate();
// value.ws.isAlive = false;
// value.ws.ping(function() {
// value.ws.send(2);
// });
});
};
// Constr.prototype.testyuyin2 = function() {
// connections.forEach(function(value) {
// value.ws.send('测试语音');
// });
// };
module.exports = Constr;

app.js

const Ws = require('./app/middleware/websocket');

const ws = new Ws(8080);
try {
ws.connect();
} catch (e) {
console.error('ws connect error:', e);
} console.log("WebSocket建立完毕")

客户端

const WebSocket = require('ws');

var lockReconnect = false;//避免重复连接
var wsUrl = "ws://127.0.0.1:8080";
var ws;
var tt;
function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch (e) {
console.log('catch' + e);
reconnect(wsUrl);
}
}
function init() {
ws.onclose = function () {
console.log('链接关闭');
reconnect(wsUrl);
};
ws.onerror = function () {
console.log('发生异常了');
reconnect(wsUrl);
};
ws.onopen = function () {
//心跳检测重置
heartCheck.start();
};
ws.onmessage = function (event) {
//拿到任何消息都说明当前连接是正常的
console.log('接收到消息' + JSON.stringify(event.data));
heartCheck.start();
}
}
function reconnect(url) {
if (lockReconnect) {
return;
};
lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}
//心跳检测
var heartCheck = {
timeout: 3000,
timeoutObj: null,
serverTimeoutObj: null,
start: function () {
// console.log('start');
var self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function () {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
ws.send("666666");
self.serverTimeoutObj = setTimeout(function () {
// console.log(111);
// console.log(ws);
ws.close();
// createWebSocket();
}, self.timeout); }, this.timeout)
}
}
createWebSocket(wsUrl);

NodeJs 实现 WebSocket 即时通讯(版本二)的更多相关文章

  1. NodeJs 实现 WebSocket 即时通讯(版本一)

    服务端代码 var ws = require("nodejs-websocket"); console.log("开始建立连接...") var game1 = ...

  2. HTML5+NodeJs实现WebSocket即时通讯

    声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 最近都在学习HTML5,做canvas游戏之类的,发现HTML5中除了canvas这个强大的工具外,还有WebSocket也很值得注意.可 ...

  3. 使用tomcat方式实现websocket即时通讯服务端讲解

    使用tomcat方式实现websocket即时通讯服务端讲解 第一种方案:使用Tomcat的方式实现 tomcat版本要求:tomcat7.0+.需要支持Javaee7 导入javeee-api的ja ...

  4. Springboot 项目源码 Activiti6 工作流 vue.js html 跨域 前后分离 websocket即时通讯

    特别注意: Springboot 工作流  前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0.0+ mybaits+maven+接 ...

  5. java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis

    A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ...

  6. IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二)

    IdentityServer4 + SignalR Core +RabbitMQ 构建web即时通讯(二) IdentityServer4 用户中心生成数据库 上文已经创建了所有的数据库上下文迁移代码 ...

  7. java SSM 框架 代码生成器 websocket即时通讯 shiro redis

    1.   权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限      角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限.      按钮权限: 给角色分配按钮权限. ...

  8. [开源] .NETCore websocket 即时通讯组件---ImCore

    前言 ImCore 是一款 .NETCore 下利用 WebSocket 实现的简易.高性能.集群即时通讯组件,支持点对点通讯.群聊通讯.上线下线事件消息等众多实用性功能. 开源地址:https:// ...

  9. [重磅开源] 比SingleR更适合的websocket 即时通讯组件---ImCore开源了

    有感而发 为什么说 SignalR 不合适做 IM? IM 的特点必定是长连接,轮训的功能用不上. 因为它是双工通讯的设计,用hub.invoke发送命令给服务端处理业务,其他就和 ajax 差不多, ...

随机推荐

  1. .Net Core自动化部署系列(二):使用Jenkins打造镜像发布流水线

    一.简介 之前写过一篇关于Jenkins搭配GitLab实现.net core项目自动发布到IIS的博文,比较简单哈,只是个Demo.本篇我们将会使用Jenkins搭配GitLab实现镜像的自动打包和 ...

  2. spring boot项目下application.properties中使用logging.path和logging.file时的细节

    logging.path仅仅用于指定日志输出的目录,且不能指定输出的文件名,且默认名为spring.log  若指定的是相对目录,则会生成在当前总项目的目录下 idea中新建sprnig boot项目 ...

  3. php微信支付v3版本签名生成

    前几天需要对接微信支付卡包营销活动需要对接微信新版SDKv3版 签名生成规则,微信的官方文档里面说明的还算可以吧,不过个人觉得不太理想- -.  自己调试的时候调试了半天才找了错误原因. https: ...

  4. Python 元组(Tuple)操作详解

    Python的元组与列表类似,不同之处在于元组的元素不能修改,元组使用小括号, 列表使用方括号,元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可 一.创建元组 代码如下: tup1 = (' ...

  5. python+selenium自动化框架

    ---恢复内容开始--- 主要使用的模块: selenium/webdriver模块(须准备Chrome驱动),主要用于调用浏览器实现自动点击. unittest模块,主要用于整合测试用例. xlrd ...

  6. 【JZOJ5264】化学

    Description Input Output Sample Input 3 10 1 2 10 Sample Output 5 Hint   题解: 这个题目通过30%部分分的提示,我们可以猜出这 ...

  7. 2. spring 应用之IOC

    本文是作者原创,版权归作者所有.若要转载,请注明出处 我们知道Spring Framework 最重要的功能就是IoC (Inversion of Control ),也叫DI(dependency ...

  8. ubuntu下安装及配置git的方法

    安装Git 一个全新的ubunt系统,需要安装Git(系统是不具有该工具的),方法如下: 在terminel中输入如下命令: sudo apt-get install git git-core git ...

  9. C# .Net Framework

    .NET Framework概述 .NET Framework是由微软开发,一个致力于敏捷软件开发.快速应用开发.平台无关性和网络透明化的软件开发平台. .NET Framework组成 .NET F ...

  10. 快速入门Maven(三)

    一.整合ssh框架的Maven项目 1.传递依赖 只添加了一个struts2-core依赖,发现项目中出现了很多jar, 这种情况叫 依赖传递 2.依赖版本冲突的解决 (1)第一声明优先原则(就是谁写 ...