在nodejs-express app中,在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文件中全局保存这个'socket',因此,能够在项目的任何地方使用它。像这样:
app.get('/on', function(req, res){
socket.on('test', function (data) {
console.log(data);
});
});
app.get('/emit', function(req, res){
socket.emit('test', "ciao");
});
我红了有一种方法可以在会话中保存'socket'连接。我的会话设置:
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()加载第一页?
答案 0 :(得分: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()
和socket.emit()
的问题,在建立连接之前不能使用它,因为套接字本身不存在。如果要向所有连接的客户端发送消息,则应该只使用全局io.sockets
对象。这将更像io.sockets.emit()
。