原文地址:https://socket.io/docs/rooms-and-namespaces/
Namespace
Socket.IO允许你与把sockets加入到某个命名空间中,这实际上就是为那些sockets分配不同的端点(endpoint)或路径(path)。
对于最小化资源(TCP连接)的数量来说,这是一个有用的特性。同时,通过引入对不同通讯频道的分离,可以分离我们的应用程序的关注点。
默认的命名空间
我们把 /
作为默认的命名空间,它是一个Socket.IO客户端默认会连接到的命名空间,还有就是它是Socket.IO服务器端默认监听的命名空间。
我们可以用 io.sockets
(或者简写成 io
) 来标识这个默认的命名空间。
// 下面的这两个例子都会发射'hi'事件给所有连接到默认命名空间'\'的socket们 io.socket.emit('hi', 'everyone'); io.emit('hi', 'everyone'); // 简写
当有socket连接到某个命名空间的时候,那个命名空间会发射一个 connection
事件,并用 Socket
实例作为参数,因此,服务器端可以通过监听 connection
事件来获取socket实例。
io.on('conncetion', function(socket) { console.log('someone connected'); // 监听'disconnect'事件 socket.on('disconnect', function(){ // ... }); });
自定义命名空间
在服务器端,我们可以用 of
函数来创建自定义的命名空间。
var nsp = io.of('/my-namespace'); // 创建自定义命名空间'/my-namespace' // 监听'connection'事件 nsp.on('connection', function(socket) { console.log('someone connected'); }); nsp.emit('hi', 'everyone!');
在客户端,你可以让Socket.IO客户端去连接自定义命名空间’/my-namespace’:
var socket = io('/my-namespace'); // 这一句里面包含了发射 ``connection`` 事件
重要提醒: 命名空间是Socket.IO协议的实现细节,并且与底层传输的实际URL无关,默认为/socket.io/…。(因此,在客户端中都要包含一下代码,来引入从服务器传输过来的信息:)
<scirpt src="/socket.io/socket.io.js"></scirpt>
Rooms
在每个命名空间的内部,你可以随意定义一些频道(channel),我们可以把频道(channel)看作房间(room),socket们能够加入(join
)或离开(leave
)频道(房间)。
加入和离开频道(房间)
你可以调用 join
函数来让socket加入到频道(房间)中。
io.on('connection', function(socket) { socket.join('some room'); // 把默认命名空间中的socket加入到'some room'频道中 });
然后,当要服务器端要进行广播(broadcast)或者发射事件(emit)时,可以通过调用 to
或者 in
(to和in是一样的)来指定某个频道(房间)。
// 服务器端给'some room'频道中的socket们发射'some event'事件 // 意思就是,这个'some event'事件只有'some room'频道中的socket们才能收到 io.to('some room').emit('some event');
如果想要离开频道,可以调用 leave
函数来实现,方法和 join
一样。
io.on('connection', function(socket) { // ... socket.leave('some room'); // 默认命名空间中的socket离开'some room'频道 });
默认房间
在Socket.IO中的每个socket都会被赋予一个随机的、独立的标识(id号) Socket#id
。为了你的方便,每个socket一开始默认会自动地加入到一个房间中,而这个房间的“房间号”,就是socket的id号。
这样的话,会让广播消息(broadcast messages)给其他sockets变得简单。
io.on('connection', function(socket) { socket.on('say to someone', function(id, msg) { socket.broadcast.to(id).emit('my message', msg); }); });
断开连接
在socket断开连接的时候,socket会自动离开(leave
)所有频道,不需要我们来手动操作离开。
从外部的世界发送消息
在某些情况下,你可能想要把事件(event)从Socket.IO进程的上下文之外发送到Socket.IO的某个房间中的socket那里。
这里有一些办法可以解决上述问题,例如让你自己的频道(房间)发送消息到进程中。
为了实现“其他外部进程和Socket.IO进程相互通讯(发射事件)”,我们创建了2个模块:
通过使用这个Redis适配器(Adapter
):
var io = require('socket.io')(3000); var redis = require('socket.io-redis'); io.adapter(redis({ host: 'localhost', port: 6379 })); // 使用adapter
你可以把消息(事件)从其他任何的进程发射(emit
)到任何频道:
var io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379}); // 这里的io代表Redis数据库进程,不是Socket.IO进程 setInterval(function() { io.emit('time', new Date); // Redis数据库进程发射'time'消息(事件) }, 5000);