socket.io
socket.io是實作HTML5 WebSocket的套件,透過WebSocket的連線,可以做到Server主動推播訊息到Client端的動作,讓Client與Server達到真正的互動...
官方網站
Github repository
https://github.com/Automattic/socket.io/
Installation
npm install socket.io
SocketIO Server實作三步驟
connect: 實作連線SocketIO Server後的動作
io.sockets.on('connection', function (socket) {
//這邊可以實作當connect發生後的一些事情
})
on: 實作某個事件發生後的動作
socket.on('event name', function (data) {
//這邊可以實作當某個名稱的event發生後的一些事情
});
emit: 實作Server主動送出某個事件跟資料
var data = ...; //希望傳送給這個socket的event
socket.emit('event name', data);
Sample Usage
下面是參考HINA網路上的Socket IO文件:http://blog.hinablue.me/entry/nodejs-first-look-socket-io 改寫呈現時間變化的頁面。
Server端實作:
var fs = require('fs') , http = require('http') // 發佈socket.io server,並且聽取8080 port , io = require('socket.io').listen(8080); /** * 實作socket io,並在connection開啟後,於callback function中實作要處理的事件 */ io.sockets.on('connection', function (socket) { /** * 每隔三秒鐘進行一次emit動作 * 而emit的內容是發佈一個news * 內容為JSON物件,以time為key,value為emit當下的時間 */ setInterval(function(){ socket.emit('news', { time: new Date() }); }, 3000); /** * 接收client傳回的事件,並且於callback內接收該data做處理 */ socket.on('my other event', function (data) { console.log('[my other event]' + data); }); }); /** * 建立server實體,目的是方便鏈結html檔案,讓前端可以連線直接測試 */ http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/html'}); //任何連線都直接讀取client01.html做回覆 res.end(fs.readFileSync(__dirname + '/client01.html', 'utf8')); }).listen(8088, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
上面程式碼中啟動了兩個server,一個為8080的socket.io server,另一個為8088的http server,而http server僅是為了提供socket.io的client連線的目的,下面是client的範例程式...(其中socket.io server不僅提供server的功用,我們還可以直接從client code中include socket.io.js,實際位置為:http://localhost:8080/socket.io/socket.io.js)
Client端實作:
<script src="http://localhost:8080/socket.io/socket.io.js"></script> <script src="http://code.jquery.com/jquery-2.0.2.min.js"></script> <script> //連結socket.io server位置 var socket = io.connect('http://localhost:8080'); //聽取news event,並在callback中處理 socket.on('news', function (data) { console.log('[on news]' + JSON.stringify(data)); //將data呈現在下方id=t的h1 tag中 $('#t').html(data.time); //觸發server另一個event,並且傳入data socket.emit('my other event', { my: 'data' }); }); </script> <h1 id="t"></h1>
Socket.io的應用相當多,而眾多的高手也都慢慢看到Node.js在Network上的實力,希望之後有更多的Socket.io相關應用跟大家分享!
SocketIO with Room
SocketIO連線後,Server端會回覆Socket一個unique id作為識別這個socket的依據,一般我們會實做一個hash存放socket id與用戶或session的一個對應表,讓之後我們可以針對使用者觸發一個event... 在Room的概念中,就像是實做了這個hash的功能,可以讓我們透過in或to指定一個Room ID做訊息的發送,操作的範例如下:
Server端實作
這邊我們實作個interval送訊息給Client的socket,並且是針對特定的Room發送...
這邊必須要注意,需要在disconnect event發生的時候clear這個interval事件,不然會造成每次disconnect時候,interval沒有清除的狀況...
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io').listen(server);
server.listen(8000);
app.get('/jquery.js', function (req, res) {
res.sendfile(__dirname + '/bower_components/jquery/src/jquery.js');
});
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
var prefix = 'room';
io.on('connection', function (socket) {
room = prefix + "-" + new Date().getTime();
socket.join(room);
var loop = setInterval(function(){
var ts = new Date().getTime();
io.sockets.in(room).emit('roomevent', {room: room, ts: ts, msg: 'sent to room...'})
}, 3000);
socket.on('event1', function (data) {
console.log(data);
});
socket.on('disconnect', function(){
clearInterval(loop);
});
});
用戶端實作
用戶端實作比較單純,在connect事件完成後,即開始listen roomevent事件,等待Server把roomevent傳送回來...
var log = require('nodeutil').logger.getInstance('test');
var socket_host = 'http://127.0.0.1:8000/'
var io = require('socket.io-client');
var opts = { reconnect: true, connect_timeout: 5000 };
var socket = io.connect(socket_host, opts);
socket.on('connect', function(){
log.info('connected...');
socket.emit('event1', {
msg: 'test...'
});
});
socket.on('news', function(data){
log.info('got news:', data);
});
socket.on('roomevent', function(data){
var id = socket.io ? socket.io.engine.id : socket.socket.sessionid;
log.info('[%s][%s]got news:', id, new Date().toString(), data);
});
進一步實作
上面的範例是由Server來決定Room ID,在現實世界裡,有可能會是Client來決定Room ID,例如在Client連線上Server後,跟Server取得認證,得到RoomID,再由Client端emit event到Server設定該RoomID...
相信大家到這邊應該有很多發想,我們暫停在這邊,給大家一個無限想像的空間 :D
其他設定
Socket.io也有支援一些細部設定的動作,例如timeout時間等等...可以參考這邊:
https://github.com/Automattic/socket.io/wiki/configuring-socket.io
設定上,需要透過socket.io instance的set method,並且在connection之前完成...
var io = require('socket.io').listen(server);
server.listen(8000);
io.set('heartbeat interval', 50);
io.on('connection', function (socket) {
//TODO: implement your code
});
這邊針對一些timeout參數做個說明...
- close timeout (defaults to 60 seconds)
Client連線的timeout時間,當client close這個connection,client仍有close timeout所設定的秒數的時間可以執行reconnect。這是Server端在成功連結後送給client的一個值...
- heartbeat timeout (defaults to 60 seconds)
Heartbeat timeout是Server連線後push給client端使用的參數,Server需要在這個設定時間內得到一個heartbeat的訊號以確保連線保持著。這個參數的設定應該要大於"heartbeat interval"。
- heartbeat interval (defaults to 25 seconds)
Heartbeat interval是Server在連線後push給client端的設定值,client端會在此設定時間傳送heartbeat訊息給server端。