javascript - 在 express 中使用套接字时出现问题

标签 javascript node.js express socket.io router

我的程序中的套接字有问题。导出“io”连接,虽然我可以从正常程序的任何部分进行广播(仅通过引用“io”),但我不能使用“socket”并与其进行广播,除非它与“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);

我的 managersocket.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

最佳答案

socket 是一个临时对象,仅在一个特定客户端连接期间存在。而且,它们可能有无数个(每个连接的客户端一个或多个)。因此,您不只是导出一个 socket 或将其塞入全局并尝试在任何地方使用它。

因此,如果您尝试做的是为刚刚收到 http 请求的用户访问 socket.io 连接,这会稍微复杂一些,并且有几种不同的方法可以实现。

我以前用过的一种方法如下所示:

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 连接设置快速 session 。这为您提供了一个存储属于某个特定客户的东西的地方(由 cookie 键入)
  2. 为 socket.io 连接设置快速 session ,这样您也可以访问 socket.io 连接中的快速 session 数据。
  3. 当发生 socket.io 连接时,将 socket.id 存储在 session 中。这使得 socket.id 可用于来自该特定客户端的 future http 请求
  4. 当某个 future 的 http 请求来自该客户端时,您可以进入 session ,获取 socket.id 值(它只是一个字符串),然后使用它来获取该用户的套接字,一旦您拥有套接字,您可以使用 socket.emit() 仅向该用户发送数据。

如果你没有其他原因使用 express-session,你也可以在 socket.io 连接连接时将 socket.id 单独放入 cookie 中,然后在连接期间从 cookie 中获取 socket.id你的 http 请求。

关于javascript - 在 express 中使用套接字时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58756713/

相关文章:

Javascript:如何在同一页面调用函数?

node.js - 如何在 Node.js 中从 xml 中抓取 url?

javascript - 非异步 Promise 回调

javascript - 成功更改密码后 Firebase 重定向到网页

javascript - 是否可以从 main.js 访问 View 中声明的 js 变量?

node.js - 更改 PouchDB 存储目录

node.js - 在 mocha 中运行 supertest 时如何获取实际的服务器错误?

javascript - Meteor、NPM 模块和光纤回调

json - Angular $http.get "Uncaught SyntaxError: Unexpected token )"没有文件引用,更别说行号了

node.js - Mongoose .find() 方法导致请求挂起