2013-03-02 51 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

相关问题