Socket.IO manipulando evento de desconexão

90

Não consigo lidar com este evento de desconexão, não sei por que o soquete não é enviado para o cliente / cliente não responde!

Servidor

io.sockets.on('connection', function (socket) {

  socket.on('NewPlayer', function(data1) {

    online = online + 1;
    console.log('Online players : ' + online);
    console.log('New player connected : ' + data1);
    Players[data1] = data1;
    console.log(Players);

  });

  socket.on('DelPlayer', function(data) {

    delete Players[data];
    console.log(Players);
    console.log('Adios' + data);

  });

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

      socket.emit('disconnected');
      online = online - 1;

  });

});

Cliente

 var socket = io.connect('http://localhost');

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

        person_name = prompt("Welcome. Please enter your name");

        socket.emit('NewPlayer', person_name);

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

            socket.emit('DelPlayer', person_name);

        });

    });

Como você pode ver, quando um cliente desconecta, o objeto Array [person_name] deve ser excluído, mas não

Raggaer
fonte
É melhor você tentar o contrário, primeiro exclua o player e depois desconecte. Porque depois que você se desconecta do servidor, o servidor não consegue mais receber o evento que o cliente emite. Mantenha o controle do soquete em vez do player, pelo qual você pode remover players facilmente.
code-jaff
Como devo excluir o player e depois desconectar? como faço para saber quando o player vai se desconectar ?.
Raggaer
4
não deveria o evento no cliente ser em 'disconnect'vez de 'disconnected'?
Sherlock
1
@Sherlock no código do cliente original do OP, eles estavam tentando ouvir um evento personalizado que estavam ativando no servidor para lógica desconectada. 'desconectar' é de fato o evento de desconexão embutido, mas não contribui diretamente para o problema que eles estão enfrentando.
Jon Church

Respostas:

173

Ok, em vez de identificar jogadores por faixa de nome com os soquetes pelos quais eles se conectaram. Você pode ter uma implementação como

Servidor

var allClients = [];
io.sockets.on('connection', function(socket) {
   allClients.push(socket);

   socket.on('disconnect', function() {
      console.log('Got disconnect!');

      var i = allClients.indexOf(socket);
      allClients.splice(i, 1);
   });
});

Espero que isso ajude você a pensar de outra maneira

código
fonte
92
Melhor usar allClients.splice(i, 1)para excluir um elemento. delete allClients[i]irá apenas definir a posição da matriz paraundefined
Yves
1
Por que está funcionando, mas a solução de rastreamento de pessoas com seus nomes não está funcionando?
sha1 de
Isso não está funcionando para mim. Aqui iobteve um valor de -1 todas as vezes. Você pode me dizer o que está acontecendo.
Vinit Chouhan
1
@VinitChouhan você provavelmente deve fazer perguntas separadas com o seu problema real.
code-jaff
Quando você obtém um valor de -1, significa que você está tentando emendar um soquete que não existe (alguém desconecta, mas você ainda não registrou a pessoa em seu allClientsarray). Eu sugiro que você apenas retorne: if (i === -1)return;antes de tentar emendá-lo.
Koen B.
23

Para aqueles como @ sha1 se perguntando por que o código do OP não funciona -

A lógica do OP para excluir o player no lado do servidor está no manipulador do DelPlayerevento, e o código que emite esse evento ( DelPlayer) está no disconnectedretorno de chamada do evento interno do cliente.

O código do lado do servidor que emite este disconnectedevento está dentro do disconnectretorno de chamada do evento que é disparado quando o soquete perde a conexão. Como o socket já perdeu a conexão, o disconnectedevento não chega ao cliente.


A solução aceita executa a lógica no disconnectevento no lado do servidor, que é disparado quando o soquete é desconectado, portanto, funciona.

TJ
fonte
6

Crie um mapa ou conjunto e, usando o evento "on connection" definido para cada soquete conectado, ao contrário do evento "uma vez desconectado", exclua esse soquete do mapa que criamos anteriormente

import * as Server from 'socket.io';

const io = Server();
io.listen(3000);

const connections = new Set();

io.on('connection', function (s) {

  connections.add(s);

  s.once('disconnect', function () {
    connections.delete(s);
  });

});
Alexander Mills
fonte
1
E seria de se esperar uma resposta detalhada com explicações e comentários de um veterano, mas acho que temos que resolver com apenas um punhado de código
Cemal
me avise se tiver dúvidas, não me lembro de ter escrito a resposta
Alexander Mills
1
Na verdade, não tenho nenhuma pergunta. Foi apenas uma crítica construtiva a um autor, que sabe melhor usar comentários e colocar descrição em uma resposta para permitir que qualquer pessoa (bem, a maioria, pelo menos) entenda seu exemplo sem incomodá-lo. De qualquer forma, feliz ano novo ..
Cemal
0

Você também pode, se desejar, usar o ID de soquete para gerenciar sua lista de jogadores desta forma.

io.on('connection', function(socket){
  socket.on('disconnect', function() {
    console.log("disconnect")
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].socket === socket.id){
        console.log(onlineplayers[i].code + " just disconnected")
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_join', function(player) {
    if(player.available === false) return
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        exists = true
      }
    }
    if(exists === false){
      onlineplayers.push({
        code: player.code,
        socket:socket.id
      })
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_leave', function(player) {
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })
})
www-data
fonte