基于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 相关文章推荐
学习YUI.Ext 第三天
Mar 10 Javascript
常用Extjs工具:Extjs.util.Format使用方法
Mar 22 Javascript
导航跟随滚动条置顶移动示例代码
Sep 11 Javascript
Javascript:为input设置readOnly属性(示例讲解)
Dec 25 Javascript
jQuery中:has选择器用法实例
Dec 30 Javascript
jquery 实现输入邮箱时自动补全下拉提示功能
Oct 04 Javascript
多个js毫秒倒计时同时进行效果
Jan 05 Javascript
浅谈js的html元素的父节点,子节点
Aug 06 Javascript
Vue.js每天必学之方法与事件处理器
Sep 06 Javascript
jQuery插件jqGrid动态获取列和列字段的方法
Mar 03 Javascript
微信小程序canvas.drawImage完全显示图片问题的解决
Nov 30 Javascript
基于Bootstrap和JQuery实现动态打开和关闭tab页的实例代码
Jun 10 jQuery
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操作文件方法问答
2007/03/16 PHP
PHP反向代理类代码
2014/08/15 PHP
php防止网站被刷新的方法汇总
2014/12/01 PHP
PHP+Ajax 检测网络是否正常实例详解
2016/12/16 PHP
php把文件设置为插件的技巧方法
2020/02/03 PHP
JS getMonth()日期函数的值域是0-11
2010/02/15 Javascript
event.X和event.clientX的区别分析
2011/10/06 Javascript
javascript动画浅析
2012/08/30 Javascript
jquery中的查找parents与closest方法之间的区别
2013/12/02 Javascript
关于Javascript作用域链的八点总结
2013/12/06 Javascript
在父页面得到zTree已选中的节点的方法
2015/02/12 Javascript
jQuery使用drag效果实现自由拖拽div
2015/06/11 Javascript
jquery表格datatables实例解析 直接加载和延迟加载
2016/08/12 Javascript
JS 事件绑定、事件监听、事件委托详细介绍
2016/09/28 Javascript
BootStrap modal模态弹窗使用小结
2016/10/26 Javascript
微信小程序入门教程
2016/11/18 Javascript
nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例
2018/01/05 NodeJs
jQuery实现form表单序列化转换为json对象功能示例
2018/05/23 jQuery
JQuery特殊效果和链式调用操作示例
2019/05/13 jQuery
基于Vue全局组件与局部组件的区别说明
2020/08/11 Javascript
Vue组件通信$attrs、$listeners实现原理解析
2020/09/03 Javascript
Python多进程multiprocessing.Pool类详解
2018/04/27 Python
python实现两张图片拼接为一张图片并保存
2019/07/16 Python
用Cython加速Python到“起飞”(推荐)
2019/08/01 Python
Python sep参数使用方法详解
2020/02/12 Python
python GUI库图形界面开发之PyQt5布局控件QGridLayout详细使用方法与实例
2020/03/06 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
简单了解python列表和元组的区别
2020/05/14 Python
巴西美妆购物网站:Kutiz Beauté
2019/03/13 全球购物
英国最大的在线快递公司之一:ParcelHero
2019/11/04 全球购物
Python里面search()和match()的区别
2016/09/21 面试题
倡议书格式
2014/04/14 职场文书
违纪开除通知书
2015/04/25 职场文书
趣味运动会加油词
2015/07/18 职场文书
关于python中readlines函数的参数hint的相关知识总结
2021/06/24 Python
Oracle数据库事务的开启与结束详解
2022/06/25 Oracle