基于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 相关文章推荐
如何使用json在前后台进行数据传输实例介绍
Apr 11 Javascript
Node.js中的事件驱动编程详解
Aug 16 Javascript
Javascript调用函数方法的几种方式介绍
Mar 20 Javascript
JS基于面向对象实现的放烟花效果
May 07 Javascript
由浅入深剖析Angular表单验证
Jul 14 Javascript
JavaScript实现倒计时跳转页面功能【实用】
Dec 13 Javascript
Angular.js自动化测试之protractor详解
Jul 07 Javascript
配置一个vue3.0项目的完整步骤
Apr 26 Javascript
javascript function(函数类型)使用与注意事项小结
Jun 10 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
Oct 31 Javascript
vue项目实现图片上传功能
Dec 23 Javascript
用js实现放大镜效果
Oct 28 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
apache配置虚拟主机的方法详解
2013/06/17 PHP
thinkphp autoload 命名空间自定义 namespace
2015/07/17 PHP
使用symfony命令创建项目的方法
2016/03/17 PHP
PHP实现一个简单url路由功能实例
2016/11/05 PHP
PHP实现的自定义数组排序函数与排序类示例
2016/11/18 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
PHP实现的AES加密、解密封装类与用法示例
2018/08/02 PHP
laravel5.6实现数值转换
2019/10/23 PHP
jQuery 菜单随滚条改为以定位方式(固定要浏览器顶部)
2012/05/24 Javascript
JavaScript?Apple设备检测示例代码
2013/11/15 Javascript
深入理解JavaScript系列(50):Function模式(下篇)
2015/03/04 Javascript
JS实现的表格行上下移动操作示例
2016/08/03 Javascript
Jquery Easyui选项卡组件Tab使用详解(10)
2016/12/18 Javascript
JavaScript实现拖拽盒子效果
2020/02/06 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
vue动态设置路由权限的主要思路
2021/01/13 Vue.js
分析Python中设计模式之Decorator装饰器模式的要点
2016/03/02 Python
运行django项目指定IP和端口的方法
2018/05/14 Python
python判断一个数是否能被另一个整数整除的实例
2018/12/12 Python
解决使用export_graphviz可视化树报错的问题
2019/08/09 Python
Python缓存技术实现过程详解
2019/09/25 Python
django框架cookie和session用法实例详解
2019/12/10 Python
python中的线程threading.Thread()使用详解
2019/12/17 Python
python集成开发环境配置(pycharm)
2020/02/14 Python
Pyqt助手安装PyQt5帮助文档过程图解
2020/11/20 Python
使用canvas一步步实现图片打码功能的方法
2019/06/17 HTML / CSS
HTML5 body设置全屏背景图片的示例代码
2020/12/08 HTML / CSS
澳大利亚最大的女装零售商:Millers
2017/09/10 全球购物
竞选学生会演讲稿
2014/04/25 职场文书
创文明城市标语
2014/06/16 职场文书
乡镇爱国卫生月活动总结
2014/06/25 职场文书
中小学校园安全广播稿
2014/09/29 职场文书
督导岗位职责
2015/02/04 职场文书
信用卡收入证明范本
2015/06/12 职场文书
基于go interface{}==nil 的几种坑及原理分析
2021/04/24 Golang
Nginx反向代理、重定向
2022/04/13 Servers