socket.io 命名空间(namespace) 与 房间 (rooms)

本文翻译了socket.io关于命名空间和房间的官方文档,解释了如何创建和管理命名空间以及如何加入和离开房间。命名空间允许对socket进行隔离,而房间则提供了在特定组内通信的功能。默认命名空间为"/",自定义命名空间可通过`of`函数设置。每个socket会自动加入以socket#id为名称的默认房间,方便广播。断开连接时,socket会自动离开所有房间。此外,介绍了如何在外部进程向socket.io发送消息的解决方案,包括socket.io-redis和socket.io-emitter模块。
摘要由CSDN通过智能技术生成

前言

网上查阅了 socket.io 官方文档,似乎没有发现最新的中文文档,有旧的,比如这个 (socket.io 中文文档) 显示为 2017年

官网的实例和网上绝大多数入门例子,几乎都一样,就一个群聊窗口,过于简单。这让很多有志于socket.io 学习的人不那么方便,这里翻译一篇官网的 socket.io 关于 namespace 和rooms 的文档,希望对大家有点帮助。如需要查阅的人多,再考虑翻译其它节。

原文地址:Rooms and Namespaces

以下为译文

命名空间(namespace,以下简称ns)

socket.io 允许你将socket 制定不同的命名空间,本质上,就是指定不同的 终点(endpoint) 或 路径(path)

这是个有用的特性,它能减少所需资源数目(tcp 连接数),同时,它通过隔离通信信道(通道 channel)达到隔离应用的多个部分

默认命名空间

我们使用默认命名空间 / ,它既是socket.io 客户端默认连接也是服务端默认监听的的命名空间。
ns 通过 io.sockets 或 简以 io 调用加以区分:

// the following two will emit to all the sockets connected to `/`
io.sockets.emit('hi', 'everyone');
io.emit('hi', 'everyone'); // short form

每个ns 都会触发一 connection 事件,并以 socket 作为参数传递到事件响应中

io.on('connection', function(socket){
  socket.on('disconnect', function(){ });
});
自定义命名空间

如果要设置一个自定义ns,你可再服务端调用 of 函数:

const nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
  console.log('someone connected');
});
nsp.emit('hi', 'everyone!');

在客户端,你可以告知 socket.io 客户端连接到对应的ns
const socket = io('/my-namespace');

重要提示:ns 仅是 socket.io 协议的实现细节,它和实际 URL 所表示的底层传输并无关系,如: /socket.io/…

房间(rooms)

在每个ns 内,你可以定义专属通道供, 这些sockets 可以 join 和 leave

Joining and leaving

你可以通过调用 join 函数 让 socket 订阅一个指定通道

io.on('connection', function(socket){
  socket.join('some room');
});

然后,在广播或者分发时可以简单的使用 to 或者 in (两者等同)
io.to('some room').emit('some event');
如果要离开通道,你可以像调用 join一样而调用 leave。 这两个方法都是异步的,接受 callback 作用参数

默认房间

在socket.io中,每个socket都会以一个 随机的、不可测的唯一标识 socket#id 区分。 为了方便,每个socket又会自动的通过这个标识id加入到一个房间。
这样让广播一个消息到其它sockets 很方便:

io.on('connection', function(socket){
  socket.on('say to someone', function(id, msg){
    socket.broadcast.to(id).emit('my message', msg);
  });
});
断开连接(disconnection)

对应连接断开,socket 或自动的 leave 所有通道,并不需要你做其它处理

从外部发送消息

有时,你可能需要在socket.io 进程上下文之外向你的 socket.io ns / rooms 中的sockets 分发事件
有一些方式可以处理这种问题,比如实现自己的通道从而向进程发送消息
为了简化此种情况,我们创建了两个模块

  • socket.io-redis
  • socket.io-emitter

通过实践redis 适配器:

const io = require('socket.io')(3000);
const redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

然后你就能从其他进程 emit 消息到任意通道

const io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
setInterval(function(){
  io.emit('time', new Date);
}, 5000);

以上为翻译全文

后记

幸好本节不长内容不多,翻译一个小时左右。对于文章尾部 “从进程外发送消息”,这个例子和说明不是很清晰,这里再补充下:

socket.io-redis 和 socket.io-emitter 是两个独立的模块,它们并不一定要组合使用。

对于实际的生产环境,我们的socket.io 服务可能是集群部署,使用多个进程或者在多个服务器,在某一进程 emit 如何让其它进程上的客户端也能收到? 此时 socket.io-redis 就是一有效工具,它通过 redis本身自带的 Pub/Sub 机制,达到也向其它进程上的客户端广播消息的目的。

而 socket.io-emmitter 才是完全从其它非socket.io 进程发送消息到socket.io 进程所要依赖的,同时结合 socket.io-redis 使用。

本文最先发布于个人博客 neveryield 的sf

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值