Проблема с сокетом при использовании в экспрессе - PullRequest
1 голос
/ 07 ноября 2019

У меня проблема с сокетом в моей программе. экспортировать соединение «io», и хотя я могу транслировать из любой части обычной программы (просто ссылаясь на «io»), я не могу использовать «сокет» и транслировать с ним, если он не находится в пределах того же соединения с «io». Я хотел бы знать, как использовать сокет из любой другой части программы, с такими функциями, как "socket.emit ()" или "socket.broadcast.emit" и т. Д. Или как вызвать этот.

Это мой index.js:

const express = require('express');
const restApi = express();
const cors = require('cors');
const server = require('http').createServer(restApi);
const rutas = require('./src/routes/Routes.js');
const io = require('./src/socket/SocketManager.js');
io.attach(server);

restApi.use(express.json());
restApi.use(express.static('public'));
restApi.use(cors());
restApi.options('*', cors());

server.listen(4040, () => console.log('Listening server in port 4040'));

restApi.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

restApi.use('/api',rutas);

my managerocket.js:

const io = require('socket.io')();

io.on('connection', function (socket) {
    console.log('NUEVA CONEXION: ',socket.id);
    socket.emit('recoger',socket.id);
});

module.exports = io;

Здесь я хотел бы использовать сокет или хотя бы вызвать функцию.

и User.js:

var io = require('../../socket/SocketManager');

var RouterUser = function(){

  this.practicafuncion = function (req,res){
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    console.log('probando entrar por rest y que salga un mensaje por socket');
    res.send({
      status:'Aprobado',
      msj:'Enviado por rest'
    });
//this works correctly.     io.sockets.emit('mensaje','**MENSAJESERVIDORPORSOCKET**');
//This is not the problem when using "socket".   socket.broadcast.emit('mensaje','**MENSAJESERVIDORPORSOCKET**');
  };
}

module.exports = function(){
  var instancia = new RouterUser();
  return instancia;
};

Это же хранилище, где весь код

https://github.com/proxirv/Socket.io-router

1 Ответ

1 голос
/ 08 ноября 2019

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"});
});

Вот шаги в этой концепции:

  1. Настройка экспресс-сессии для обычных http-соединений. Это дает вам место для хранения вещей, принадлежащих одному конкретному клиенту (с ключом cookie)
  2. Настройте express-session для соединения socket.io, чтобы вы также могли иметь доступ к данным express-session в socketСоединения .io.
  3. Когда происходит соединение с socket.io, сохраните файл socket.id в сеансе. Это делает socket.id доступным для будущих http-запросов от этого конкретного клиента
  4. Когда от этого клиента поступает какой-либо будущий http-запрос, вы можете войти в сеанс и получить значение socket.id (которое простоstring), а затем используйте его, чтобы получить сокет для этого пользователя, и, получив сокет, вы можете использовать socket.emit() для отправки данных только этому пользователю.

Если вы этого не сделалиУ вас нет других причин для использования экспресс-сессии, вы также можете просто поместить socket.id в файл cookie при подключении к разъему socket.io, а затем получить socket.id из файла cookie во время запроса http.

...