基于Node.js的WebSocket通信实现


Posted in Javascript onMarch 11, 2017

node的依赖包

node中实现Websocket的依赖包有很多,websocket、ws均可,本文选取ws来实现,首先安装依赖

npm install ws

聊天室实例

假如A,B,C,D用户均通过客户端连接到Websocket服务,其中每个人发的消息都需要将其通过Websocket转发给其他人,此场景类似于服务端将A的消息广播给组内其他用户。

服务端实现

首先来看服务端程序,具体的工作流程分以下几步:

  1. 创建一个WebSocketServer的服务,同时监听8080端口的连接请求。
  2. 每当有新的客户端连接该WebSocket成功时,便将该连接push到连接池的数组中。
  3. 监听message事件,当该事件发生时,遍历连接池,以连接为单位将该消息转发到对应的客户端
  4. 监听close事件,当该事件发生时,将该连接移出连接池

服务端代码

var WebSocketServer = require('ws').Server,
  wss = new WebSocketServer({port: 8080});

// 连接池
var clients = [];

wss.on('connection', function(ws) {
  // 将该连接加入连接池
  clients.push(ws);
  ws.on('message', function(message) {
    // 广播消息
    clients.forEach(function(ws1){
      if(ws1 !== ws) {
        ws1.send(message);
      }
    })
  });

  ws.on('close', function(message) {
    // 连接关闭时,将其移出连接池
    clients = clients.filter(function(ws1){
      return ws1 !== ws
    })
  });
});

客户端实现

<html>
<input type="text" id="text">
<input type="button" onclick="sendMessage()" value="online">
<script>
  var ws = new WebSocket("ws://localhost:8080");

  ws.onopen = function (e) {
    console.log('Connection to server opened');
  }
  ws.onmessage = function(event) { 
    console.log('Client received a message', event); 
  }; 
  ws.onclose = function (e) {
    console.log('connection closed.');
  }
  function sendMessage() {
      ws.send(document.getElementById('text').value);
  }
</script>
</html>

如何发现用户?

通过上述的demo可以看到,WebSocket都是基于连接的,也就是说我们知道data是从那个connection发过来,但并不知道使用客户端的是李雷或者韩梅梅,这可如何是好?再想另一种场景,李雷只想给韩梅梅发消息,不想将消息广播给其他客户端,此时我们就需要在Server端能够标识用户身份和连接的对应关系。

于是,需要在客户端连接到WebSocket之后,紧接着再发一次请求,告诉Server我的user_id是多少,Server将此user_id与connection之间的关系存储在hashmap中,至此就建立了user_id与connection的对应关系。当需要发送消息给对应的客户端,从此hashmap中取出对应用户的connection信息,调用其send方法发出消息即可。

依赖包

npm install hashmap

服务端实现

var WebSocketServer = require('ws').Server, webSocketServer = new WebSocketServer({port: 8080});
var HashMap = require('hashmap');

// record the client
var userConnectionMap = new HashMap();
var connectNum = 0;

// connection
webSocketServer.on('connection', function(ws) {
  ++ connectNum;
  console.log('A client has connected. current connect num is : ' + connectNum);
  ws.on('message', function(message) {
    var objMessage = JSON.parse(message);
    var strType = objMessage['type'];

    switch(strType) {
      case 'online' : 
        userConnectionMap.set(objMessage['from'], ws);
        break;
      default:
        var targetConnection = userConnectionMap.get(objMessage['to']);
        if (targetConnection) {
          targetConnection.send(message);
        }
    }
  });

  ws.on('close', function(message) {
    var objMessage = JSON.parse(message);
    userConnectionMap.remove(objMessage['from']);
  });
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
二级域名或跨域共享Cookies的实现方法
Aug 07 Javascript
框架页面高度自动刷新的Javascript脚本
Nov 01 Javascript
JQuery插件fancybox无法在弹出层使用左右键的解决办法
Dec 25 Javascript
jquery中each方法示例和常用选择器
Jul 08 Javascript
浅析JS动态创建元素【两种方法】
Apr 20 Javascript
值得分享的bootstrap table实例
Sep 22 Javascript
JSON与XML的区别对比及案例应用
Nov 11 Javascript
Bootstrap警告(Alerts)的实现方法
Mar 22 Javascript
小程序自定义组件实现城市选择功能
Jul 18 Javascript
简述pm2常用命令集合及配置文件说明
May 30 Javascript
JavaScript中将值转换为字符串的五种方法总结
Jun 06 Javascript
详解vue中使用transition和animation的实例代码
Dec 12 Vue.js
js原生Ajax的封装和原理详解
Mar 11 #Javascript
ThinkPHP+jquery实现“加载更多”功能代码
Mar 11 #Javascript
Bootstrap的Carousel配合dropload.js实现移动端滑动切换图片
Mar 10 #Javascript
基于Bootstrap框架实现图片切换
Mar 10 #Javascript
angularjs ui-router中路由的二级嵌套
Mar 10 #Javascript
AngularJS ui-router (嵌套路由)实例
Mar 10 #Javascript
微信小程序手势操作之单触摸点与多触摸点
Mar 10 #Javascript
You might like
为什么《星际争霸》是测试人工智能的理想战场
2019/12/03 星际争霸
多人战的战术与战略
2020/03/04 星际争霸
德生H-501的评价与改造
2021/03/02 无线电
php使浏览器直接下载pdf文件的方法
2013/11/15 PHP
yii数据库的查询方法
2015/12/28 PHP
PHP随机获取未被微信屏蔽的域名(微信域名检测)
2017/03/19 PHP
Laravel5.5以下版本中如何自定义日志行为详解
2018/08/01 PHP
PHP实现一个按钮点击上传多个图片操作示例
2020/01/23 PHP
YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例
2020/03/18 PHP
js正确获取元素样式详解
2009/08/07 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
jQuery 文本框得失焦点的简单实例
2014/02/19 Javascript
文字垂直滚动之javascript代码
2015/07/29 Javascript
以JavaScript来实现WordPress中的二级导航菜单的方法
2015/12/14 Javascript
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
2016/12/15 Javascript
jQuery动态添加元素无法触发绑定事件的解决方法分析
2018/01/02 jQuery
利用React Router4实现的服务端直出渲染(SSR)
2019/01/07 Javascript
JavaScript实现随机五位数验证码
2019/09/27 Javascript
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
2011/03/13 Python
django 按时间范围查询数据库实例代码
2018/02/11 Python
python 借助numpy保存数据为csv格式的实现方法
2018/07/04 Python
Python eval的常见错误封装及利用原理详解
2019/03/26 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
python循环嵌套的多种使用方法解析
2019/11/29 Python
Python 高效编程技巧分享
2020/09/10 Python
html5时钟实现代码
2010/10/22 HTML / CSS
Notino芬兰:购买香水和化妆品
2019/04/15 全球购物
50道外企软件测试面试题
2014/08/18 面试题
管理部副部长岗位职责范文
2014/03/09 职场文书
大学生就业策划书范文
2014/04/04 职场文书
安全标兵事迹材料
2014/08/17 职场文书
高中国旗下的演讲稿
2014/08/28 职场文书
小学生学习保证书
2015/02/26 职场文书
昆虫记读书笔记
2015/06/26 职场文书
反邪教学习心得体会
2016/01/15 职场文书
前端框架ECharts dataset对数据可视化的高级管理
2022/12/24 Javascript