socket.io namespaces and rooms (譯)

前言

網上查閱了 socket.io  官方文檔,彷佛沒有發現最新的中文文檔,有舊的,好比這個  (socket.io 中文文檔)   是  2017 年的。redis

官網的實例和網上絕大多數入門例子,幾乎都同樣,就一個羣聊窗口,過於簡單。這讓不少有志於socket.io 學習的人不那麼方便,這裏翻譯一篇官網的 socket.io 關於 namespace 和rooms 的文檔,但願對你們有點幫助。如須要查閱的人多,再考慮翻譯其它節。服務器

原文地址:Rooms and Namespaces異步

如下爲譯文socket

命名空間(namespace,如下簡稱ns)

socket.io 容許你將socket 制定不一樣的命名空間,本質上,就是指定不一樣的 終點(endpoint) 或 路徑(path)tcp

這是個有用的特性,它能減小所需資源數目(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 函數:ui

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');socket.io

重要提示: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 使用。

相關文章
相關標籤/搜索