Socket.IO obsługuje zdarzenie rozłączenia

88

Nie mogę obsłużyć tego zdarzenia rozłączenia, nie wiem, dlaczego gniazdo nie jest wysyłane do klienta / klienta nie odpowiada!

serwer

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;

  });

});

Klient

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

        });

    });

Jak widać, gdy klient rozłącza się, obiekt Array [person_name] powinien zostać usunięty, ale tak nie jest

Raggaer
źródło
Lepiej spróbuj odwrotnie, najpierw usuń odtwarzacz, a następnie odłącz. Ponieważ po odłączeniu się od serwera serwer nie będzie w stanie odebrać zdarzenia, które wyemituje klient. Śledź raczej gniazdo niż odtwarzacz, dzięki czemu możesz łatwo usunąć graczy.
code-jaff
Jak usunąć odtwarzacz, a następnie odłączyć? skąd mam wiedzieć, kiedy gracz się rozłączy?
Raggaer,
4
czy wydarzenie na kliencie nie powinno być 'disconnect'zamiast tego 'disconnected'?
Sherlock,
1
@Sherlock w oryginalnym kodzie klienta OP próbowali nasłuchiwać niestandardowego zdarzenia, które wyzwalali po stronie serwera dla rozłączonej logiki. „odłączenie” jest rzeczywiście wbudowanym zdarzeniem rozłączenia, ale nie przyczynia się bezpośrednio do problemu, którego doświadczają.
Jon Church

Odpowiedzi:

170

Ok, zamiast identyfikować graczy po nazwie toru z gniazdami, przez które się połączyli. Możesz mieć taką implementację

serwer

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

Mam nadzieję, że pomoże ci to myśleć w inny sposób

code-jaff
źródło
90
Lepiej użyć allClients.splice(i, 1)do usunięcia elementu. delete allClients[i]po prostu ustawi pozycję tablicy naundefined
Yves
1
Dlaczego to działa, ale rozwiązanie do śledzenia osób za pomocą ich nazw nie działa?
sha1
To nie działa dla mnie. Tutaj iza każdym razem otrzymano wartość -1. Czy możesz mi powiedzieć, co się dzieje.
Vinit Chouhan
1
@VinitChouhan prawdopodobnie powinieneś zadać osobne pytanie dotyczące aktualnego problemu.
code-jaff
Kiedy uzyskasz wartość -1, oznacza to, że próbujesz połączyć gniazdo, które nie istnieje (ktoś się rozłącza, ale nie zarejestrowałeś jeszcze osoby w swojej allClientstablicy). Proponuję po prostu wrócić: if (i === -1)return;przed próbą połączenia.
Koen B.
23

Dla takich jak @ sha1 zastanawiających się, dlaczego kod OP nie działa -

Logika OP do usuwania gracza po stronie serwera znajduje się w module obsługi DelPlayerzdarzenia, a kod, który emituje to zdarzenie ( DelPlayer), znajduje się w wewnętrznym disconnectedwywołaniu zwrotnym zdarzenia klienta.

Kod po stronie serwera, który emituje to disconnectedzdarzenie, znajduje się w disconnectwywołaniu zwrotnym zdarzenia, które jest uruchamiane, gdy gniazdo traci połączenie. Ponieważ gniazdo już utraciło połączenie, disconnectedzdarzenie nie dociera do klienta.


Zaakceptowane rozwiązanie wykonuje logikę na disconnectzdarzenie po stronie serwera, które jest uruchamiane w momencie rozłączenia gniazda, dzięki czemu działa.

TJ
źródło
6

Utwórz mapę lub zestaw i używając zdarzenia „on connection” ustawionego dla każdego połączonego gniazda, w odwrotnej kolejności zdarzenie „Once rozłącz” usuń to gniazdo z utworzonej wcześniej mapy

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
źródło
1
I można by się spodziewać szczegółowej odpowiedzi z wyjaśnieniami i komentarzami od weterana, ale myślę, że musimy poprzestać na kilku kodach
Cemal
daj mi znać, jeśli masz pytania, nie pamiętam, bym pisał odpowiedź
Alexander Mills,
1
Właściwie nie mam żadnego pytania. To była tylko konstruktywna krytyka skierowana do autora, który wie lepiej, jak używać komentarzy i opisu miejsca w odpowiedzi, aby każdy (a przynajmniej najbardziej) mógł zrozumieć Twój przykład bez wkurzania Cię. Tak czy inaczej, szczęśliwego Nowego Roku ..
Cemal
0

Możesz także, jeśli chcesz, użyć identyfikatora gniazda do zarządzania listą graczy w ten sposób.

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)
  })
})
dane-www
źródło