【问题标题】:Socket.io receiving data from multiple sockets in NodeSocket.io 从 Node 中的多个套接字接收数据
【发布时间】:2017-06-14 13:56:35
【问题描述】:

我几天前才开始使用 Node 进行开发。我目前正在开发一个使用 Node 作为服务器端应用程序的在线游戏。此应用程序仅向客户端提供 .html 和 .js 文件并处理游戏逻辑。 我正在使用 Socket.io 与客户端交换数据。当一个新的客户端通过 Socket.io 连接到服务器时,程序会寻找一个空间(包含两个用户的套接字和处理逻辑的游戏对象的对象数组)并放置用户(注册插座)在里面。 我已经能够正确地向每个客户端发送精灵的位置,但是我在从每个套接字检索数据时遇到问题:如果我尝试将一些数据从客户端发送到服务器,则该数据仅流经其中一个两个套接字,无论是哪个客户端发送的。

初始化房间数组

for(var i = 0; i < roomsNumber; i++) {
  //player1 and player 2 are going to store the sockets
  rooms[i] = { player1 : null, player2 : null, game: null};
}

Socket.io 处理连接

var io = require('socket.io')(server);

io.on('connection', function(socket){
  console.log("We have a new client: " + socket.id);
  insertPlayer(socket);

  socket.on('disconnect', function() {
    console.log("Client has disconnected: " + socket.id);
    removePlayer(socket);
  });
});

将客户添加到房间

function insertPlayer(socket) { //Check for an empty spot in a room
  for(var i = 0; i < rooms.length; i++) {
    if(!rooms[i].player1) {
      rooms[i].player1 = socket; //Register the socket to the room
      checkRooms();
      return;
    }
    if(!rooms[i].player2) {
      rooms[i].player2 = socket; //Register the socket to the room
      checkRooms();
      return;
    }
  }
}

在房间满时创建 Game 对象(并在玩家离开时销毁它)

function checkRooms() { //Checks if a room is full to initialize the game
  for(var i = 0; i < rooms.length; i++) {
    if(rooms[i].player1 && rooms[i].player2 && !rooms[i].game) {
      rooms[i].game = new Game([rooms[i].player1, rooms[i].player2]); //The constructor passes the sockets
      console.log('New game started');
    }
    if((!rooms[i].player1 || !rooms[i].player2) && rooms[i].game) {
      rooms[i].game.endGame();
      rooms[i].game = null;
      console.log('Game stopped');
    }
  }
}

在 Game 类中接收数据

constructor(sockets) {
  this.sockets = sockets;
  this.snakes = [];
  var self = this;

  for(var i = 0; i < this.sockets.length; i++) {
    this.snakes[i] = new Snake(i*100 + 100, 200);
    var currentSnake = this.snakes[i];
    var currentSocket = this.sockets[i];

  currentSocket.on('keyPressed', function(data) {
    currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite 
    console.log(currentSocket.id + " - " + data);
  });
}

【问题讨论】:

  • 我认为我们在这里看不到足够的代码来理解或查看问题所在。例如,在此代码中,您从客户端套接字接收数据的唯一位置是在 Game 类中,但您没有显示何时创建 Game 类以及如何创建它所具有的套接字列表。如果您最初创建的游戏中只有两个套接字,那么这就是您将注册以接收keyPressed 事件的所有套接字。
  • 当您说“无论哪个客户端发送数据,数据仅流经两个套接字中的一个”时,您是什么意思。你究竟观察到什么让你这么说?而且,您发现了什么问题?
  • 目前的游戏包含两条在框架中移动的蛇。每条蛇由一个用户控制,每个用户都可以看到他的蛇和敌人的蛇。要改变蛇的方向,用户必须按下箭头按钮(这会将一些数据发送到服务器)。当我尝试游戏时(在浏览器的两个选项卡上),我看到了两条蛇,当我按下第一个选项卡上的箭头键时,蛇(比如说数字 1)改变了方向。当我更改标签并再次按下箭头按钮时,改变方向的蛇仍然是蛇号 1。
  • 好的,我在下面的回答(这是在我看到你最近的评论之前写的)应该可以解决这个确切的问题。将来,当您首次发布问题时,请在您的问题中添加对问题的非常好的和详细的描述,并确保包含与该问题相关的所有代码。你会更快得到答案。
  • 成功了!谢谢你。下次我会尽量准确一点

标签: javascript node.js sockets npm socket.io


【解决方案1】:

我发现Game 构造函数中的currentSnake 变量存在问题。该变量的作用域是您的整个构造函数,因此那里只有一个变量,但是您试图为每个玩家设置一个单独的变量,但这是行不通的。因此,每次收到keyPressed 消息时,无论密钥来自哪个玩家,您都在对同一条蛇进行操作。

如果您使用的是 node.js v6+,则将该构造函数中的 var currentSnake 更改为 let currentSnake,以便将变量单独限定为 for 循环的每次调用。

constructor(sockets) {
  this.sockets = sockets;
  this.snakes = [];
  var self = this;

  for(var i = 0; i < this.sockets.length; i++) {
    this.snakes[i] = new Snake(i*100 + 100, 200);
    // change these to be declared with let so they are separately scoped 
    //   for each invocation of the for loop
    let currentSnake = this.snakes[i];
    let currentSocket = this.sockets[i];

    currentSocket.on('keyPressed', function(data) {
      currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite 
      console.log(currentSocket.id + " - " + data);
    });
  }
}

或者,如果您运行的是旧版本的 node.js,请切换到 .forEach() 以替换 for 循环,因为这也会为循环的每次调用创建一个新的单独范围。

constructor(sockets) {
  this.sockets = sockets;
  this.snakes = [];
  var self = this;

  this.sockets.forEach(function(currentSocket, i) {
    this.snakes[i] = new Snake(i*100 + 100, 200);
    var currentSnake = this.snakes[i];

    currentSocket.on('keyPressed', function(data) {
      currentSnake.updateDirection(data); //Calls a Game method that updates the direction of the sprite 
      console.log(currentSocket.id + " - " + data);
    });
  });
}

【讨论】:

    猜你喜欢
    • 2016-12-19
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 2018-01-19
    相关资源
    最近更新 更多