Socket.IO обрабатывает событие отключения

88

Не могу обработать это событие отключения, не знаю, почему сокет не отправляется клиенту / клиенту не отвечает!

Сервер

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;

  });

});

Клиент

 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);

        });

    });

Как видите, когда клиент отключает, объект массива [person_name] должен быть удален, но не

Raggaer
источник
Лучше попробуйте другой способ, сначала удалите плеер, а затем отключите. Поскольку после того, как вы отключитесь от сервера, сервер не сможет получить событие, которое испускает клиент. Следите за гнездом, а не за плеером, с помощью которого вы можете легко удалить игроков.
code-jaff
Как мне удалить плеер, а затем отключить? как я узнаю, когда игрок отключится ?.
Raggaer
4
не должно быть событие на клиенте 'disconnect'вместо 'disconnected'?
Шерлок
1
@Sherlock в исходном клиентском коде OP они пытались прослушать настраиваемое событие, которое они запускали на стороне сервера для отключенной логики. «Disconnect» действительно является встроенным событием отключения, но оно не влияет напрямую на проблему, с которой они сталкиваются.
Джон Черч

Ответы:

170

Хорошо, вместо того, чтобы идентифицировать игроков по имени, следите за сокетами, через которые они подключились. У вас может быть такая реализация, как

Сервер

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);
   });
});

Надеюсь, это поможет вам думать по-другому

шифровальщик
источник
90
Лучше использовать allClients.splice(i, 1)для удаления элемента. delete allClients[i]просто установит позицию массива наundefined
Yves
1
Почему это работает, но решение для отслеживания людей с их именами не работает?
sha1
У меня это не работает. Здесь iкаждый раз получалось значение -1. Вы можете сказать мне, что происходит?
Винит Чоухан
1
@VinitChouhan, вам, вероятно, следует задать отдельный вопрос по вашей реальной проблеме.
code-jaff
Когда вы получаете значение -1, это означает, что вы пытаетесь соединить несуществующий сокет (кто-то отключается, но вы еще не зарегистрировали этого человека в своем allClientsмассиве). Я предлагаю вам просто вернуться: if (i === -1)return;прежде чем пытаться его склеить.
Koen B.
23

Для тех, кто вроде @ sha1 задается вопросом, почему код OP не работает -

Логика OP для удаления игрока на стороне сервера находится в обработчике DelPlayerсобытия, а код, который генерирует это событие ( DelPlayer), находится в обратном disconnectedвызове внутреннего события клиента.

Код на стороне сервера, который генерирует это disconnectedсобытие, находится внутри disconnectобратного вызова события, который запускается, когда сокет теряет соединение. Поскольку сокет уже потерял соединение, disconnectedсобытие не доходит до клиента.


Принятое решение выполняет логику disconnectсобытия на стороне сервера, которое запускается, когда сокет отключается, следовательно, работает.

TJ
источник
6

Создайте карту или набор и, используя событие «при подключении», установите для него каждый подключенный сокет, в обратном случае событие «после отключения» удалите этот сокет из карты, которую мы создали ранее.

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);
  });

});
Александр Миллс
источник
1
И можно было бы ожидать подробного ответа с пояснениями и комментариями от ветерана, но я полагаю, что нам нужно ограничиться лишь кучей кода
Джемаль
дайте мне знать, если у вас есть вопросы, я не помню, как писал ответ
Александр Миллс
1
У меня вообще нет вопросов. Это была просто конструктивная критика в адрес автора, который лучше знает, как использовать комментарии и помещать описание в ответ, чтобы позволить любому (ну, по крайней мере, по крайней мере) понять ваш пример, не отвлекая вас. В любом случае, с Новым годом ..
Джемаль
0

Вы также можете, если хотите, использовать идентификатор сокета для управления списком игроков следующим образом.

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
источник