socket
- это временный объект, который существует только на время одного конкретного клиентского соединения. И их может быть миллионы (по одному или более для каждого подключенного клиента). Таким образом, вы не просто экспортируете один socket
или заполняете его в глобальном масштабе и пытаетесь использовать его везде.
Итак, если вы пытаетесь получить доступ к соединению socket.ioдля пользователя, для которого вы только что получили запрос http, это немного сложнее, и есть несколько различных способов приблизиться к нему.
Один из подходов, который я использовал ранее, показан ниже:
const express = require('express');
const app = express();
const server = app.listen(80);
const io = require('socket.io')(server);
const expsession = require('express-session');
const path = require('path');
// install session middleware
const sessionMiddleware = expsession({
secret: 'random secret',
saveUninitialized: true,
resave: true
});
// run session middleware for regular http connections
app.use(sessionMiddleware);
// run session middleware for socket.io connections
io.use(function(socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
// when a socket.io connection connects, put the socket.id into the session
// so it can be accessed from other http requests from that client
io.on('connection', function(socket) {
// socket.handshake.headers
console.log(`socket.io connected: ${socket.id}`);
// save socket.io socket in the session
console.log("session at socket.io connection:\n", socket.request.session);
socket.request.session.socketio = socket.id;
socket.request.session.save();
});
// any arbitrary express route definition
// Note: you can't send socket.io data in a request that loads an HTML page
// because that client hasn't yet established the socket.io connection
// for that page. The socket.io connections will be created after
// the browser loads this page.
app.get("/", function(req, res) {
const session = req.session;
console.log("\n\npage load\n---------------------------\n");
console.log("session:\n", session);
res.sendFile(path.join(__dirname, "socket-io-session.html"));
});
// Upon an API call from a page that already has a socket.io connection,
// respond to the API call and send something to that page's socket.io socket
app.get("/api/test", function(req, res) {
const session = req.session;
io.sockets.connected[session.socketio].emit('show', "sending some data");
console.log("session:\n", session);
console.log("session.socketio:\n", session.socketio);
res.json({greeting: "hello"});
});
Вот шаги в этой концепции:
- Настройка экспресс-сессии для обычных http-соединений. Это дает вам место для хранения вещей, принадлежащих одному конкретному клиенту (с ключом cookie)
- Настройте express-session для соединения socket.io, чтобы вы также могли иметь доступ к данным express-session в socketСоединения .io.
- Когда происходит соединение с socket.io, сохраните файл socket.id в сеансе. Это делает socket.id доступным для будущих http-запросов от этого конкретного клиента
- Когда от этого клиента поступает какой-либо будущий http-запрос, вы можете войти в сеанс и получить значение socket.id (которое простоstring), а затем используйте его, чтобы получить сокет для этого пользователя, и, получив сокет, вы можете использовать
socket.emit()
для отправки данных только этому пользователю.
Если вы этого не сделалиУ вас нет других причин для использования экспресс-сессии, вы также можете просто поместить socket.id в файл cookie при подключении к разъему socket.io, а затем получить socket.id из файла cookie во время запроса http.