Socket.IO簡述

Socket.IO用於瀏覽器與node.js之間實現實時通信。Socket.IO設計的目標是支持任何的瀏覽器,任何Mobile設備。支持主流的PC瀏覽器 (IE,Safari,Chrome,Firefox,Opera等),Mobile瀏覽器(iphone Safari/ipad Safari/android WebKit/WebOS WebKit等)。

Socket.IO支持如下方式的通信方式,根據瀏覽器的支持程度,自動選擇使用哪種技術進行通信:

  • WebSocket
  • Flash Socket
  • AJAX long-polling
  • AJAX multipart streaming
  • Forever IFrame
  • JSONP polling

Socket.IO解決了實時的通信問題,並統一了服務端與客戶端的編程方式。啓動了socket以後,就像建立了一條客戶端與服務端的管道,兩邊可以互通有無。

 

關於engine.io

engine.io是一個Socket.IO的抽象實現,作爲Socket.IO的服務器和瀏覽器之間交換的數據的傳輸層。它不會取代Socket.IO,它只是抽象出固有的複雜性,支持多種瀏覽器,設備和網絡的實時數據交換。

 

 

 

Socket.IO的基本使用方式

建立服務器

例:創建io服務器的兩種簡單的方法。

複製代碼
var io = require('Socket.IO')();

//

var Server = require('Socket.IO');
var io = new Server();
複製代碼

 

 

 

服務器配置

Socket.IO服務器的配置項與engine.io相同。

  • pingTimeout (Number):等待響應包的時間,單位爲毫秒。默認爲60000。
  • pingInterval (Number):設定每隔在一定時間發送一個ping包,可以用於心跳包的設置。默認爲25000。
  • maxHttpBufferSize (Number):消息最大大小,可用於避免DoS攻擊。默認爲 10E7。
  • allowRequest (Function):該配置項爲一個函數。第一個參數是一個一個握手或連接請求。第二個參數是一個回調函數function(err,success),success是boolean值,false表示連接失敗;err是錯誤碼。該函數可以用於決定是否繼續。
  • transports (<Array> String):指定傳輸的連接方式。默認爲['polling', 'websocket']。
  • allowUpgrades (Boolean):是否允許升級傳輸協議。 默認爲true。
  • cookie (String|Boolean):HTTP Cookie的名字。默認爲io。

 

通過Node http server使用Socket.IO

複製代碼
// Server (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); }); }); // Client (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 使用Socket.IO

複製代碼
// Server (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);
  });
});



// Client (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>
複製代碼

 

 

 

 

 

發送以及接收事件

Socket.IO 提供了默認事件(如:connect, message, disconnect)。另外,Socket.IO允許發送並接收自定義事件。

事件的發送:

複製代碼
//發送給對應的客戶端
socket.emit('message',"this is a test");

//發送給所有客戶端
io.sockets.emit('message',"this is a test");

//發送消息給指定socketId的客戶端。
io.sockets.socket(socketid).emit('message','for your eyes only');

//發送自定義的事件
socket.emit("my-event","this is a test");
複製代碼

 

 

事件的接收:

socket.on("event name",function(data){
  //data爲接收到的數據。
});

 

 

 

示例代碼

例1:

複製代碼
// note, io.listen(<port>) will create a http server for you
var io = require('Socket.IO').listen(80);

io.sockets.on('connection', function (socket) {
  io.sockets.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.sockets.emit('user disconnected');
  });

});
複製代碼

 

 

 

例2:

複製代碼
// Server (app.js)

var io = require('Socket.IO').listen(80);
io.sockets.on('connection', function (socket) {
  socket.on('ferret', function (name, fn) {
    fn('woot');
  });
});


// Client (index.html)
<script>
  var socket = io(); // TIP: io() with no args does auto-discovery
  socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
    socket.emit('ferret', 'tobi', function (data) {
      console.log(data); // data will be 'woot'
    });
  });
</script>
複製代碼

 

 

 

 

廣播消息

廣播消息由服務器發送,會發送給除了當前連接的其他所有客戶端。

//發送給除了發送者之外的所有客戶端。
socket.broadcast.emit('message',"this is a test");

 

 

例:廣播用戶連接的自定義事件。

var io = require('Socket.IO').listen(80);
io.sockets.on(
'connection', function (socket) { socket.broadcast.emit('user connected'); });

 

 

 

發送易變(volatile)的數據

volatile 意思大概是說,當服務器發送數據時,客戶端因爲各種原因不能正常接收,比如網絡問題、或者正處於長連接的建立連接階段。此時會讓我們的應用變得 suffer,那就需要考慮發送 volatile 數據。

複製代碼
var io = require('Socket.IO').listen(80);

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

  socket.on('disconnect', function () {
    clearInterval(tweets);
  });
});
複製代碼

 

即使客戶端沒連線,一樣可以這樣發送,服務器會自動丟棄發送失敗的數據。

 

 

命名空間

通過命名空間可以爲Socket.IO設置子程序。默認命名空間爲“/”,Socket.IO默認連接該路徑。

使用of()函數可以自定義命名空間。

複製代碼
// Server (app.js)
var io = require('Socket.IO').listen(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' });
  });


// Client (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>
複製代碼

 

 

 

 

房間

房間是Socket.IO提供的一個非常好用的功能。房間相當於爲指定的一些客戶端提供了一個命名空間,所有在房間裏的廣播和通信都不會影響到房間以外的客戶端。

 

進入房間與離開房間

使用join()方法將socket加入房間:

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

 

使用leave()方法離開房間:

socket.leave('some room');

 

在房間中發送消息

在某個房間中發送消息:

io.to('some room').emit('some event');

 

to()方法用於在指定的房間中,對除了當前socket的其他socket發送消息。

socket.broadcast.to('game').emit('message','nice game');

 

in()方法用於在指定的房間中,爲房間中的所有有socket發送消息。

io.sockets.in('game').emit('message','cool game');

 

 

當socket進入一個房間之後,可以通過以下兩種方式在房間裏廣播消息:

複製代碼
//向my room廣播一個事件,提交者會被排除在外(即不會收到消息)
io.sockets.on('connection', function (socket) {
    //注意:和下面對比,這裏是從客戶端的角度來提交事件
    socket.broadcast.to('my room').emit('event_name', data);
}

//向another room廣播一個事件,在此房間所有客戶端都會收到消息
//注意:和上面對比,這裏是從服務器的角度來提交事件
io.sockets.in('another room').emit('event_name', data);

//向所有客戶端廣播
io.sockets.emit('event_name', data);
複製代碼

 

除了向房間廣播消息之外,還可以通過以下API來獲取房間的信息。

複製代碼
//獲取所有房間的信息
//key爲房間名,value爲房間名對應的socket ID數組
io.sockets.manager.rooms

//獲取particular room中的客戶端,返回所有在此房間的socket實例
io.sockets.clients('particular room')

//通過socket.id來獲取此socket進入的房間信息
io.sockets.manager.roomClients[socket.id]
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章