基于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 相关文章推荐
fireworks菜单生成器mm_menu.js在 IE 7.0 显示问题的解决方法
Oct 20 Javascript
仿猪八戒网左下角的文字滚动效果
Oct 28 Javascript
jQuery添加删除DOM元素方法详解
Jan 18 Javascript
实例浅析js的this
Dec 11 Javascript
JS中的phototype详解
Feb 04 Javascript
JS简单实现滑动加载数据的方法示例
Oct 18 Javascript
Node实战之不同环境下配置文件使用教程
Jan 02 Javascript
JS中利用FileReader实现上传图片前本地预览功能
Mar 02 Javascript
讲解vue-router之什么是编程式路由
May 28 Javascript
Vue 菜单栏点击切换单个class(高亮)的方法
Aug 22 Javascript
Vue动态创建注册component的实例代码
Jun 14 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
Aug 20 Javascript
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
PHP读取文件内容后清空文件示例代码
2014/03/18 PHP
php中base_convert()进制数字转换函数实例
2014/11/20 PHP
[原创]php实现 data url的图片生成与保存
2016/12/04 PHP
php常用的工具开发整理
2019/09/26 PHP
仅IE6/7/8中innerHTML返回值忽略英文空格的问题
2011/04/07 Javascript
输入框过滤非数字的js代码
2014/09/18 Javascript
jquery表单对象属性过滤选择器实例分析
2015/05/18 Javascript
js实现简洁的滑动门菜单(选项卡)效果代码
2015/09/04 Javascript
Bootstrap Fileinput文件上传组件用法详解
2016/05/10 Javascript
Ionic默认的Tabs模板使用实例
2016/08/29 Javascript
JavaScript数组去重的6个方法
2017/01/21 Javascript
详解vuelidate 对于vueJs2.0的验证解决方案
2017/03/09 Javascript
angular学习之ngRoute路由机制
2017/04/12 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
原生javascript实现文件异步上传的实例讲解
2017/10/26 Javascript
nodejs实现超简单生成二维码的方法
2018/03/17 NodeJs
小程序实现左滑删除功能
2018/10/30 Javascript
JS监听滚动和id自动定位滚动
2018/12/18 Javascript
通过vue手动封装on、emit、off的代码详解
2019/05/29 Javascript
bootstrap-paginator服务器端分页使用方法详解
2020/02/13 Javascript
window下eclipse安装python插件教程
2017/04/24 Python
使用Python实现一个栈判断括号是否平衡
2018/08/23 Python
Django 视图层(view)的使用
2018/11/09 Python
从0开始的Python学习014面向对象编程(推荐)
2019/04/02 Python
元组列表字典(莫烦python基础)
2019/04/03 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
2019/10/12 Python
pytorch 实现cross entropy损失函数计算方式
2020/01/02 Python
Python Django2 model 查询介绍(条件、范围、模糊查询)
2020/03/16 Python
Nike俄罗斯官方网站:Nike RU
2021/03/05 全球购物
介绍一下.net和Java的特点和区别
2012/09/26 面试题
机械工程师求职自我评价
2013/09/23 职场文书
销售自我评价
2013/10/22 职场文书
行政人事经理职位说明书
2014/03/05 职场文书
2014物价局民主生活会对照检查材料思想汇报
2014/09/24 职场文书
党员个人自我剖析材料
2014/10/08 职场文书
MySQL优化之如何写出高质量sql语句
2021/05/17 MySQL