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

        });

    });

Як бачите, коли клієнт від'єднує об'єкт Array [ім'я_імені], його слід видалити, але ні


Краще спробуйте інше, спочатку видаліть програвач, а потім відключіть. Оскільки після від’єднання від сервера сервер не зможе отримати подію, яку випускає клієнт. Слідкуйте за сокетом, а не за плеєром, за допомогою якого ви можете легко видалити гравців.
code-jaff

Як мені видалити програвач, а потім відключити? як я знаю, коли гравець збирається від'єднатись ?.
Raggaer

4
чи не має бути подія на клієнті 'disconnect'замість 'disconnected'?
Шерлок

1
@Sherlock у вихідному коді клієнта OP намагалися прослухати власну подію, яку вони запускали на стороні сервера для відключеної логіки. "відключення" - це дійсно вбудована подія відключення, але це не сприяє безпосередньому вирішенню проблеми.
Джон Черч

Відповіді:


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. Чи можете ви сказати мені, що відбувається?
Vinit Chouhan

1
@VinitChouhan, вам, мабуть, слід задати окреме запитання щодо вашої фактичної проблеми.
code-jaff

Коли ви отримуєте значення -1, це означає, що ви намагаєтеся зростити сокет, який не існує (хтось від'єднує, але ви ще не зареєстрували людину у своєму allClientsмасиві). Я пропоную вам просто повернутися: if (i === -1)return;перш ніж намагатись зростити його.
Koen B.

23

Для таких, як @ sha1, які задаються питанням, чому код OP не працює -

Логіка OP для видалення програвача на стороні сервера знаходиться в обробнику DelPlayerподії, а код, який випромінює цю подію ( DelPlayer), знаходиться у disconnectedзворотному виклику клієнта.

Код на стороні сервера, який випромінює цю disconnectedподію, знаходиться всередині disconnectзворотного виклику події, який запускається, коли сокет втрачає з'єднання. Оскільки сокет вже втратив підключення, disconnectedподія не надходить до клієнта.


Прийняте рішення виконує логіку щодо disconnectподії на стороні сервера, яка запускається, коли сокет відключається, отже, працює.


6

Створіть карту або набір, і використовуючи для встановленого для неї кожного підключеного сокета подію "on connection", у зворотному випадку "один раз відключіть" видаліть цей сокет із карти, яку ми створили раніше

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
І можна було б очікувати детальної відповіді з поясненнями та коментарями від ветерана, але, мабуть, нам доведеться розрахуватися лише кількома кодами
Cemal

дайте мені знати, якщо у вас є питання, я не пам’ятаю, як написав відповідь
Олександр Міллс

1
У мене насправді немає питань. Це була просто конструктивна критика на адресу автора, який знає, що краще використовувати коментарі та містити опис у відповіді, щоб дозволити будь-кому (ну, як мінімум) зрозуміти ваш приклад, не вислуховуючи вас. У будь-якому разі, з новим роком ..
Cemal

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)
  })
})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.