SocketIO识别用户断开连接的内容

时间:2015-07-04 23:26:36

标签: node.js express socket.io serverside-javascript

我正在制作一个使用Express,Socket.io和Http服务器的简单Node.js游戏。所有用户都存储在服务器上的多维对象中。这就是服务器端代码的工作方式:

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static(__dirname + '/'));

var playerList = {};

createPlayer = function(array,width,height,spdx,spdy,x,y,color,name,id) {
  var player = {
    width:width,
    height:height,
    spdx:spdx,
    spdy:spdy,
    x:x,
    y:y,
    wKeyDown:false,
    aKeyDown:false,
    sKeyDown:false,
    dKeyDown:false,
    color:color,
    name:name,
    id:id
  }
  array[id] = player;
}

io.on('connection', function(socket) {
  socket.on('new player', function(id, name) {
    id = parseInt(id);
    if (!playerList[id]) {
      createPlayer(playerList,25,25,4,4,Math.round(Math.random() * 800),Math.round(Math.random() * 600),randomColor(),name,id);
    }

    socket.on('pressW', function(id, keyDown) {
      playerList[id].wKeyDown = keyDown;
    });
    socket.on('pressA', function(id, keyDown) {
      playerList[id].aKeyDown = keyDown;
    });
    socket.on('pressS', function(id, keyDown) {
      playerList[id].sKeyDown = keyDown;
    });
    socket.on('pressD', function(id, keyDown) {
      playerList[id].dKeyDown = keyDown;
    });
  });

  socket.on('disconnect', function() {

  });
};

sendPlayerList = function() {
  //newPlayerList is used to prevent client from seeing other users IDs
  var newPlayerList = {};
  var count = 0;
  for (var q in playerList) {
    player = {
      x:playerList[q].x,
      y:playerList[q].y,
      width:playerList[q].width,
      height:playerList[q].height,
      color:playerList[q].color,
      name:playerList[q].name,
    }
    newPlayerList[count] = player;
    count++;
  }

  io.emit('edit playerlist', newPlayerList);
}

SPLInterval = setInterval(sendPlayerList, 1000);

以下是连接的客户端代码:

var id;
$('#playbutton').click(function() {
  var name = document.getElementById('name').value;
  id = Math.floor(Date.now() * Math.random());
  socket.emit('new player', id, name);
});

在客户端,在更新循环中,当游戏想要告诉服务器您的输入时,它会发出您的输入:

update = function() {
    ctx.clearRect(0,0,canvas.width,canvas.height);
    if (document.hasFocus()) {
      socket.emit('pressD', id, dKeyDown);
      socket.emit('pressS', id, sKeyDown);
      socket.emit('pressA', id, aKeyDown);
      socket.emit('pressW', id, wKeyDown);
    }else{
      socket.emit('pressD', id, false);
      socket.emit('pressS', id, false);
      socket.emit('pressA', id, false);
      socket.emit('pressW', id, false);
    }
    clientUpdatePlayer();
    updatePlayers();
  }
}

var updateInterval = setInterval(update, 31.25);

更新玩家的功能只是根据服务器发送的玩家列表吸引玩家。

我的问题是,当用户断开连接时,他们会留在播放器列表中。 我不明白我应该如何解决这个问题。我通过获取他们从客户端发送的ID来识别用户,但是当他们断开连接时我无法获得用户的ID。

还有更多代码,但我试图只包含我认为必要的代码。如果需要,我愿意提供更多代码。

5 个答案:

答案 0 :(得分:9)

您可以将id值存储在父作用域中,disconnect事件处理程序可以访问该作用域:

io.on('connection', function(socket) {
  var userId;
  socket.on('new player', function(id, name) {
    userId = id = parseInt(id);
    // ...
  });

  socket.on('disconnect', function() {
    delete playerList[userId];
  });
};

答案 1 :(得分:3)

这对我有用:

在每个新的连接或上线的用户上生成一个套接字ID,将其添加到用户对象,并将其添加到所有在线用户的数组中。

const users = [];
io.on('connection', (socket) => {
const socketId = socket.id; 


socket.on('user online', (data) => {

    users.push({ ...data, socketId });
    io.emit('view user online', user);
  });

然后在disconnect中,使用forEach遍历数组中的每个对象,然后使用for遍历并delete对象中的每个键:< / p>

 socket.on('disconnect', () => {
    users.forEach((user) => {
      if (user.socketId === socket.id) {
        for (const key in user) {
          delete user[key];
        }
      }
        });

        logger(`A user has disconnected`);
      });
      });
});

调整您想要的方式。

答案 2 :(得分:2)

也许我迟到了,但我遇到了类似的事情,发现这很难,这可能对某人有帮助。

检测用户是否断开连接的最佳方法是首先在套接字会话中设置用户名。

从发件人

发送客户端的名称
socket.emit("newUser", username);

并在服务器上

socket.on('newUser',function (username) {
     // we store the username in the socket session for this client
     socket.username = username;
});

当用户断开连接时,在断开连接事件中找到

socket.on('disconnect', function () {
    var connectionMessage = socket.username + " Disconnected from Socket " + socket.id;
    console.log(connectionMessage);
  });

你可以从那里拿走它。

答案 3 :(得分:0)

我们可以使用套接字ID将数据作为数据存储在playerList中。每当用户断开连接时,您都可以根据套接字ID从对象中删除元素

var playerList = {};
io.on("connection", socket => {

if (!Object.values(playerList).includes(playername) && playername != null) {
      var U_data = {
        [socket.id]: playername
      };
      playerList = { ...playerList, ...U_data };
    }
  socket.on("disconnect", function(e, id) {
    console.log(socket.id);
    delete playerList[socket.id];
    io.emit("broadcast", Object.values(playerList));

  });
}

答案 4 :(得分:0)

var users = [];
socket.on('newUser', (username) => {
    users.push({
        id: socket.id,
        username: username
    });
});
socket.on('disconnect', () => {
     const presentUser = users.find(user => user.id == socket.id);
     users = users.filter(user => user != presentUser);
});