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 によってソケットを参照します。認証時にサーバーに渡されるオブジェクトのタイプの例を次に示します。

{
  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 を持つ 2 つのソケットが作成されます。

socket.on()との使用に関する質問についてsocket.emit()は、ソケット自体が存在しないため、接続が確立される前にそれを使用することはできません。接続されているすべてのクライアントにメッセージを送信する場合は、グローバルio.socketsオブジェクトを使用する必要があります。それはもっと似ているでしょうio.sockets.emit()

于 2013-09-19T01:18:07.767 に答える