【问题标题】:socket.io connects with same socket idsocket.io 使用相同的套接字 id 连接
【发布时间】:2020-11-11 09:40:54
【问题描述】:

当前端在服务器之前加载时,我的套接字会产生问题, 我的问题是

1.我从多个客户端的cookies中得到相同的socketid

2.我只有一个客户端连接了服务器的多个socketid

3.当我遇到这个问题时,我的 API 调用将无法正常工作,并且我不会从我的数据库中获取任何数据

当我重新启动服务器以及使用不同的客户端多次刷新前端时,我也遇到了这个问题

我的服务器端代码

const mongoose = require("mongoose");
express = require("express");
app = express();
bodyParser = require("body-parser");
cookieParser = require("cookie-parser");
cors = require("cors");
user = require("./routes/user");
message = require("./routes/message");
http = require("http");
server = http.createServer(app);
io = require("socket.io")(server);
var userdata = require("./controllers/user");

mongoose
  .connect(process.env.DATABASE, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then(() => {
    console.log("DB CONNECTED");
  })
  .catch((err) => console.log(err));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(cors());
app.use(express.json());
app.use("/use", user);
app.use("/use", message);

let users = [];

io.on("connection", (socket) => {
  socket.on("done", () => {
    let userdata = require("./controllers/user");
    console.log("connected");
    userdata.userdata &&
      users.push({ userid: userdata.userdata._id, socketid: socket.id });
    console.log(users);
  });

  socket.broadcast.emit("message");
  socket.on("more", function (c) {
    console.log(c.a, c.b);
    let d = users.find((s) => s.userid === c.b);
    if (d) {
      return io.to(d.socketid).emit("message", c);
    }
  });

  socket.on("disconnect", () => {
    console.log(socket.id);
    if (users) {
      for (let e = 0; users.length; e++) {
        if (users[e] && users[e].socketid === socket.id) {
          return users.splice(e, 1);
        }
      }
    }
    console.log(users);
    return console.log("disconnected");
  });
});
// app.use();
const port = process.env.PORT || 8000;

server.listen(port, () => {
  console.log(`app is running at ${port}`);
});

我发现我的问题是由userdata引起的,当我删除了与userdata相关的所有内容后,即使重新加载服务器也没有任何问题。

这里的userdata来自一个叫做isSignedIn的中间件,这个中间件在这个网页的每个API调用之前被调用,所以userdata会经常更新通过前端代码。这是我的 isSignedIn 函数

exports.isSignedIn = async (req, res, next) => {
  const header = req.headers["authorization"];
  const token = header && header.split(" ")[1];
  if (!token) return res.json("no token");
  jwt.verify(token, "jsdhbcjsd", (err, User) => {
    if (err) return res.json(`${err}  not signedin`);
    req.User = User;
    exports.userdata = User;
    next();
  });
};

我尝试调用 isSignedIn() 而不是导入 userdata,这样会好很多,但我从 headers 收到错误>,所以我不能调用这个函数。

调用此函数时出现错误isSignedIn()

Promise {
  <rejected> TypeError: Cannot read property 'headers' of undefined
      at exports.isSignedIn (D:\message\backend\controllers\user.js:86:22)

它讲述了这一行

 const header = req.headers["authorization"];

我确保只有在使用 await 调用 API 后才会在前端连接套接字,以便在连接到套接字之前更新 userdata。我已经在控制台中对其进行了测试,套接字调用 API 后才连接

async componentDidMount() {
  //my API calls
      await this.friends(token);
      await this.findfriends(token);

  //connect the socket
      this.start();
      this.recieve();
 }}    

我的前端代码

const client = require("socket.io-client");
var socket
export default class Home extends Component {
 constructor(props) {
    super(props);
    this.start = this.start.bind(this);
    this.send = this.send.bind(this);
    this.recieve = this.recieve.bind(this);
    this.friends= this.friends.bind(this);
    this.findfriends= this.findfriends.bind(this);
 }
 start(){
 socket=client("http://localhost:8000");
 }
 send(){
 socket.emit("more", c)
 }
 recieve(){
 socket.on("message", c)
 }
 async componentDidMount() {
  //my API calls
      await this.friends(token);
      await this.findfriends(token);

  //connect the socket
      this.start();
      this.recieve();
 }}    

 render(){
 return(my data)
 }
}


【问题讨论】:

  • 这个let userdata = require("./controllers/user");在做什么?对于每个用户,您将获得与该语句完全相同的userdata。因此,当您执行 users.push({ userid: userdata.userdata._id, socketid: socket.id }); 时,您每次都推送完全相同的 userid 属性。
  • 另外,在这个for (e = 0; users.length; ++e) { 中,更改为for (let e = 0; e &lt; users.length; ++e) {,这样您就不会在for 循环中使用意外/隐式/未声明的全局,因此您的循环有适当的界限。
  • 在阅读了您的 cmets 之后,我已经从服务器中删除了与用户数据相关的所有内容。刷新服务器时我没有遇到这个问题,只有当我删除时我才在前端获得相同的 socketid服务器重新加载之前的cookie。用户数据来自名为isSighnedin的中间件,该中间件在此页面的每个API之前调用,并且仅在客户端登录时才重定向到此页面。我正在导入用户数据,因为我不能调用它由于一些标头问题而在此处起作用。
  • 我的 isSigned 函数exports.isSignedIn = async (req, res, next) =&gt; { const header = req.headers["authorization"]; const token = header &amp;&amp; header.split(" ")[1]; if (!token) return res.json("no token"); jwt.verify(token, "jsdhbcjsd", (err, User) =&gt; { if (err) return res.json('${err} not signedin'); req.User = User; exports.userdata = User; next(); }); };
  • 多行代码在 cmets 中不可读。请使用“编辑”链接将代码添加到您的问题中,然后发布您更新问题的评论。

标签: node.js reactjs sockets websocket socket.io


【解决方案1】:

您不能在中间件中重新分配 exports.userdata = User;。这将影响使用这些导出的每个请求,因此无论他们是哪个用户,它们最终都会看到相同的userdata。这就是你困惑的根源。每个模块只有一个exports 对象,使用该模块的每个人都会看到相同的exports 对象。因此,您不能将exports 用于特定于请求的数据。

我看到你已经分配了req.User = User。这是放置特定于请求的数据的合适位置,并且该数据的其他用户在处理请求时应该从req.User 获取数据,而不是从导出的对象获取数据。这将使每个请求和每个用户的数据分开。

【讨论】:

  • 只有在执行isSignedIn() 之后我才会得到req.User ,否则它将是null,但我无法调用此函数。我可以将它用作我的中间件路由,并在我的路由函数中使用req.Userrouter.post("/message", isSignedIn, createmessage); 。在这里我可以在createmessage()中使用req.User。当我调用isSignedIn()时,我得到了未定义的标题,当我调用时request未定义isSignedIn(request,response,next),安装resquest 后,我得到response 未定义。没有npm可以安装response
  • 我尝试在不使用isSignedIn 的情况下获取标头,但不使用路由器就无法获取它
  • @ram - 您可以使用您查找的用户的唯一位置是在同一请求的路由处理程序中。该数据属于该请求。因此,您在中间件之后的路线中使用它。这就是中间件的用途以及它的工作原理。您不能获取一些特定于路由或特定于用户的数据并将其填充到某个模块变量中,然后再使用它。这将使服务器只适用于一个用户。
【解决方案2】:

在考虑了请求标头之后,这是不可能的,我想,为什么我不能从套接字中获取用户ID,当它刚刚连接时,然后我尝试了这段代码,它工作得很好

客户端

 start = () => {
    socket = client("http://localhost:8000");
    socket.on("connect", () => {
      return socket.emit("userinfo", this.state.User._id);
    });
  };

服务器端

 socket.on("userinfo", function (user) {
    users.push({ userid: user, socketid: socket.id });
    console.log("C O N N E C T E D");
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 2013-08-20
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2018-04-24
    相关资源
    最近更新 更多