2013-03-02 85 views
9

所以我試圖讓我的套接字工作在我的socket.on('連接',...) 我想使用最近的版本得到這個工作:Socket.io - 0.9.13,Express - 3.1.0和其他模塊的最新版本。如何使用redis,express和socket.io獲得會話?

無論如何,我已經嘗試使用兩個模塊'connect-redis'和'session.socket.io',他們都有類似的問題。在我的代碼中,我有2個redis存儲(socketio.RedisStore和require('connect-redis')(express)),現在這個程序運行良好,但是因爲express和socket.io需要共享會話數據,我想知道這個設置是否會正確使用會話?會話存儲需要成爲express/socketio的同一個對象嗎?有點灰色地帶給我,因爲2 RedisStore的將在後臺使用相同的數據庫?

我已經嘗試過在兩個地方都使用socket.io redisStore或connect-redis redisStore,但是socket.io不喜歡connect-redis redisStore並且表達不像socketio.redisStore。

如果我使用connect-redis的RedisStore然後socket.io/lib/manager.js抱怨: this.store.subscribe(... 的TypeError對象#有沒有方法 '訂閱'

如果我使用socketio.RedisStore然後快遞/ node_modules /連接/ lib中/中間件/ session.js抱怨: 類型錯誤:對象#有沒有方法 'GET'

*注意:我寧願得到session.socket.io插件工作,但是當我使用該插件進行相同的設置時,express(也)抱怨: TypeError:Object#沒有方法'get'

因此,我可以使用2個不同的RedisStores進行會話,或者我需要以某種方式讓一個或另一個爲兩者工作,如果有的話,有關如何解決的任何想法?

我當前的代碼如下所示:

var 
    CONST = { 
     port: 80, 
     sessionKey: 'your secret sauce' 
    }; 

var 
    redis = require('redis'); 

var 
    express = require('express'), 
    socketio = require('socket.io'), 
    RedisStore = require('connect-redis')(express); 

var 
    redisStore = new RedisStore(), 
    socketStore = new socketio.RedisStore(); 

var 
    app = express(), 
    server = require('http').createServer(app), 
    io = socketio.listen(server); 

app.configure(function(){ 
    app.use(express.cookieParser(CONST.sessionKey)); 
    app.use(express.session({ secret: CONST.sessionKey, store: redisStore })); 
    app.use(express.static(__dirname + '/test')); 
    app.get('/', function (req, res) {res.sendfile(__dirname + '/test/' + 'index.htm');}); 
}); 

io.configure(function(){ 
    io.set('log level', 1); 
    io.enable('browser client minification'); 
    io.enable('browser client etag'); 
    io.enable('browser client gzip'); 
    io.set('store', socketStore); 
}); 

io.sockets.on('connection', function(socket){ 
    socket.emit('message', 'Test 1 from server') 
}); 

server.listen(CONST.port); 

console.log('running...'); 

回答

4

io.configure裏面,你必須插座與HTTP會話鏈接。

這是一段代碼,提取cookie(這是使用socket.io與xhr-polling,我不知道這是否適用於websocket,雖然我懷疑它會工作)。

var cookie = require('cookie'); 
var connect = require('connect'); 

var sessionStore = new RedisStore({ 
    client: redis // the redis client 
}); 

socketio.set('authorization', function(data, cb) { 
    if (data.headers.cookie) { 
    var sessionCookie = cookie.parse(data.headers.cookie); 
    var sessionID = connect.utils.parseSignedCookie(sessionCookie['connect.sid'], secret); 
    sessionStore.get(sessionID, function(err, session) { 
     if (err || !session) { 
     cb('Error', false); 
     } else { 
     data.session = session; 
     data.sessionID = sessionID; 
     cb(null, true); 
     } 
    }); 
    } else { 
    cb('No cookie', false); 
    } 
}); 

然後,您可以使用訪問會話:

socket.on("selector", function(data, reply) { 
    var session = this.handshake.session; 
    ... 
} 

這也有它檢查存在有效會話的好處是,在用戶所以只有您可以登錄使用套接字。不過,你可以使用不同的邏輯。

+0

感謝您的快速回復,所以這是同樣的解決方案,如果我想使用session.socket.io插件?或者這是一個不同的問題? – 2013-03-02 01:35:51

+0

這不使用session.socket.io插件並且適用於最新版本的socket.io和express。 – 2013-03-02 01:38:36

+0

ahhh好吧,我可以放棄這一點,感謝您的幫助。 – 2013-03-02 01:43:54

4

看你的最後一個音符(將無法通過使用Redis的多個進程共享其狀態)我有同樣的問題,並找到了解決辦法:

var express = require("express.io"); 
var swig = require('swig'); 
var redis = require('redis'); 
var RedisStore = require('connect-redis')(express); 

workers = function() { 
    var app = express().http().io(); 

    app.use(express.cookieParser()); 
    app.use(express.session({ 
     secret: 'very cool secretcode', 
     store: new RedisStore({ client: redis.createClient() }) 
    })); 

    app.io.set('store', new express.io.RedisStore({ 
     redisPub: redis.createClient(), 
     redisSub: redis.createClient(), 
     redisClient: redis.createClient() 
    })); 


    app.get('/', function(req, res) { 
     res.render('index'); 
    }); 

    app.listen(3000); 


    app.io.route('ready', function(req){ 
     //setup session stuff, use session stuff, etc. Or make new routes 
    }); 
}; 

cluster = require('cluster'); 
numCPUs = require('os').cpus().length; 

if (cluster.isMaster) 
{ 
    for (var i = 0; i < numCPUs; i++) 
    { 
     cluster.fork(); 
    } 
} 
else 
{ 
    workers(); 
} 
+0

這裏的關鍵是'app.io.set 'store',new express.io.RedisStore({'使用express.io.RedisStore。謝謝! – ruffrey 2014-03-22 17:24:45

相關問題