socket.io 概述

2018-10-18 11:01 更新

如何使用socket.io

安裝



$ npm install socket.io
    

使用 Node http 服務器


服務端 (app.js)


var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
      

客戶端 (index.html)


<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>
      

使用 Express 3/4

服務端 (app.js)


var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
      

客戶端 (index.html)


<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>
      

使用 Express 2.x

服務端 (app.js)


var app = require('express').createServer();
var io = require('socket.io')(app);

app.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
      

客戶端 (index.html)


<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>
      

發(fā)送和接收事件

Socket.IO 允許觸發(fā)和相應自定義事件。 除了 connect、 messagedisconnect 之外,你還可以觸發(fā)自定義事件:

服務端


// 提示: io(<port>) 會自動創(chuàng)建 http 服務器
var io = require('socket.io')(80);

io.on('connection', function (socket) {
  io.emit('this', { will: 'be received by everyone'});

  socket.on('private message', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ', msg);
  });

  socket.on('disconnect', function () {
    io.emit('user disconnected');
  });
});
      

指定命名空間


如果你可以控制應用中的所有消息和事件,使用默認的 / 命名空間就夠了。但如果你使用了第三方代碼,或是要將代碼分享給其他人使用, socket.io 還可以為 socket 提供命名空間。

這樣就可以 復用 單個連接。 下面的例子中, socket.io 只用了一個 WebSocket 連接,而不是兩個。

服務端 (app.js)


var io = require('socket.io')(80);
var chat = io
  .of('/chat')
  .on('connection', function (socket) {
    socket.emit('a message', {
        that: 'only'
      , '/chat': 'will get'
    });
    chat.emit('a message', {
        everyone: 'in'
      , '/chat': 'will get'
    });
  });

var news = io
  .of('/news')
  .on('connection', function (socket) {
    socket.emit('item', { news: 'item' });
  });
      

客戶端 (index.html)


<script>
  var chat = io.connect('http://localhost/chat')
    , news = io.connect('http://localhost/news');
  
  chat.on('connect', function () {
    chat.emit('hi!');
  });
  
  news.on('news', function () {
    news.emit('woot');
  });
</script>
      

發(fā)送不穩(wěn)定消息(可能丟失的消息)

有時一些消息可能會丟失。假定你要做一款應用,用于顯示實時的包含關鍵詞 bieber 的推文。

如果客戶端還不能接收消息 (由于網絡較慢或者其他問題,或者是使用長連接方式連接,且正處于請求-響應循環(huán)中),但是不能接收所有的關于 bieber 的推文并不會嚴重影響你的應用。

這種情況下,你可以將這些消息作為不穩(wěn)定消息發(fā)送。

服務端


var io = require('socket.io')(80);

io.on('connection', function (socket) {
  var tweets = setInterval(function () {
    getBieberTweet(function (tweet) {
      socket.volatile.emit('bieber tweet', tweet);
    });
  }, 100);

  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});
    

發(fā)送并獲取數據(回執(zhí))

有時,你需要在客戶端確認消息已接收后執(zhí)行一個回調。

要做到這一點,只需要為 .send.emit 方法的最后一個參數傳入一個函數即可。 更重要的是,當你使用 .emit 方法時,確認是由您完成的,這意味著您也可以傳遞數據:

服務端 (app.js)


// 注意:這里的示例加入了譯者自己的理解,如果覺得不通,可以查看官網示例
// 流程應該是這樣的:
// 1.客戶端觸發(fā)了 'ferret' 事件,發(fā)送數據 'tobi' 給服務器,
//   并注冊了一個回調 function(data){...} 以等待服務端的回執(zhí)(acknowledgement)
// 2.服務端響應 'ferret' 事件,并在適當的時候調用 cb() ,為客戶端返回回執(zhí),
//   這里的 'woot' 可有可無,如果沒有,那么客戶端回調中的 data 就是 undefined
// 3.客戶端收到回執(zhí) ,執(zhí)行預先注冊的回調 function(data){...} 
var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.on('ferret', function (name, cb) {
    console.log(name); // name 將會是 'tobi'
    // 這里的回調 cb() 在服務器接收到消息后可以調用,以通知客戶端服務器已接收消息;
    // 調用時還可以返回數據給客戶端(這里是 'woot')
    cb('woot');
  });
});
      

客戶端 (index.html)


<script>
  // 注意:這里的示例加入了譯者自己的理解,如果覺得不通,可以查看官網示例
  var socket = io(); // TIP: io() 不帶參數會開啟自動發(fā)現
  socket.on('connect', function () { // TIP: 你也可以直接監(jiān)聽具體事件,而不用監(jiān)聽 `connect` 事件!
    socket.emit('ferret', 'tobi', function (data) {
      // 回調將在服務器端調用 cb() 后執(zhí)行
      console.log(data); // data 將會是 'woot'
    });
  });
</script>
      

廣播消息


要廣播消息,只需要在 emitsend 方法前面加上 broadcast 標志即可。廣播意味著將消息發(fā)送給除發(fā)送者以外的所有人。

服務端


var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});
    

用作跨瀏覽器的 WebSocket


如果要使用 WebSocket 的語法,只需要調用 send 方法并監(jiān)聽 message 事件即可:

服務端 (app.js)


var io = require('socket.io')(80);

io.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});
      

客戶端 (index.html)


<script>
  var socket = io('http://localhost/');
  socket.on('connect', function () {
    socket.send('hi');

    socket.on('message', function (msg) {
      // my msg
    });
  });
</script>
      

如果你不關心自動重連邏輯等問題, 可以看看 Engine.IO, 這是一個 WebSocket 語義的傳輸層。 Socket.IO 用的也是它。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號