您可能听说过的不是将套接字保存到会话中,而是通过会话 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()
.