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

Wea*_*tie 3 serverside-javascript node.js express socket.io

我正在制作一个使用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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

msc*_*dex 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];
  });
};
Run Code Online (Sandbox Code Playgroud)

  • 这对多个用户有效吗?这不是只是将 userId 变量更改为最近连接的玩家吗? (2认同)
  • 为什么正确的答案呢?id = 1的用户A连接到服务器,并且userId为1,而id = 2的userB连接到userA,userId为2之后,服务器! (2认同)

Vik*_*war 7

也许我参加聚会迟到了,但我遇到了类似的事情,并且发现它很难,这可能会对某人有所帮助。

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

在发出时从客户端发送名称

socket.emit("newUser", username);
Run Code Online (Sandbox Code Playgroud)

并在服务器上

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

当用户断开连接时发现在断开连接事件上

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

你可以从那里拿走它。