2

在 nodejs-express 应用程序中,我在 server.js 文件中设置了 socket-io 连接。做这样的事情很好

var server = require('http').createServer(app)
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {

    // how can I save globally this 'socket'?

});

我想将此“套接字”全局保存在 server.js 文件中,以便能够在项目中的任何地方使用它。像这样:

app.get('/on', function(req, res){
    socket.on('test', function (data) {
        console.log(data);
    });
});
app.get('/emit', function(req, res){
    socket.emit('test', "ciao");
});

我红色有一种方法可以在会话中保存“套接字”连接。我的会话设置:

app.configure(function(){
    // ....
    app.use(express.cookieParser(SITE_SECRET));
    app.use(express.session({
        secret : 
        ,store  : new MongoStore({
        mongoose_connection : mongoose.connection
        ,db: mongoose.connections[0].db
    })
    ,cookie: { maxAge: new Date(Date.now() + (1000*60*60*24*30*12)) }
    }));
     ...
});

有什么好的方法吗?

此外,在进行此保存后,如果尚未打开连接,如何使用 socket.on() 和 socket.emit() 加载第一页?

4

1 回答 1

3

您可能听说过的不是将套接字保存到会话中,而是通过会话 cookie 引用套接字,该会话 cookie 在套接字授权过程中传递给服务器。在授权期间,这是传递给服务器的对象类型的示例:

{
  headers: req.headers,       // <Object> the headers of the request
  time: (new Date) +'',       // <String> date time of the connection
  address: socket.address(),  // <Object> remoteAddress and remotePort object
  xdomain: !!headers.origin,  // <Boolean> was it a cross domain request?
  secure: socket.secure,      // <Boolean> https connection
  issued: +date,              // <Number> EPOCH of when the handshake was created
  url: request.url,           // <String> the entrance path of the request
  query: data.query           // <Object> the result of url.parse().query or a empty object
}

我们感兴趣的是headers属性,我们可以在其中找到连接套接字的会话 cookie。然后我们在授权期间解析 cookie:

// pass same objects from Express to Socket.IO so they match
var parseCookie = express.cookieParser(SITE_SECRET);
var store = new MongoStore({
  mongoose_connection: mongoose.connection,
  db: mongoose.connections[0].db
});

io.configure(function() {
  io.set('authorization', function(handshake, callback) {
    if (handshake.headers.cookie) {
      parseCookie(handshake, null, function(err) {
        // we used the signedCookies property since we have a secret
        // save the session ID to the socket object, we can access it later
        handshake.sessionID = handshake.signedCookies['connect.sid'];

        store.get(handshake.sessionID, function(err, session) {
          // we have the same Express session, reference it
          socket.session = session;
          callback(null, true);
        });
      });
    } else {
      // they client has no session yet, don't let them connect
      callback('No session.', false);
    }
  });
});

app.use(parseCookie);
app.use(express.session({
  secret: SITE_SECRET,
  store: store,
  cookie: {maxAge: new Date(Date.now() + (1000*60*60*24*30*12))}
}));

然后,一旦我们保存了会话 ID,我们就可以使用典型的连接事件:

var server = require('http').createServer(app)
var io = require('socket.io').listen(server);

var clients = {};
io.sockets.on('connection', function (socket) {
  // save to a global object
  var session = socket.handshake.sessionID;
  clients[session] = socket;

  socket.on('disconnect', function() {
    delete clients[session];
  });
});

然后我们有一个通过 cookie 签名的全局引用。然后我们可以像这样访问套接字:

app.get('/path', function(req, res) {
  var socket = clients[req.sessionID];
  socket.emit('Socket client accessed route.');
});

请记住,您可能必须为具有多个选项卡的客户端在全局逻辑中添加一些逻辑,这将导致两个套接字具有相同的授权 cookie。

至于您关于使用socket.on()and的问题socket.emit(),在建立连接之前您不能使用它,因为套接字本身不存在。如果您想向所有连接的客户端发送消息,那么您应该只使用全局io.sockets对象。它会更像io.sockets.emit().

于 2013-09-19T01:18:07.767 回答