前言

网上查阅了 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
49 声望4 粉丝

资深互联网 noiser