연결 해제 이벤트를 처리하는 Socket.IO


90

이 연결 끊기 이벤트를 처리 할 수 ​​없습니다. 소켓이 클라이언트에 전송되지 않는 이유 / 클라이언트가 응답하지 않는 이유를 모릅니다!

섬기는 사람

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]는 삭제되어야하지만 삭제되지는 않습니다.


다른 방법으로 시도하는 것이 좋습니다. 먼저 플레이어를 삭제 한 다음 연결을 끊습니다. 서버와의 연결이 끊어지면 서버는 클라이언트가 생성하는 이벤트를 수신 할 수 없습니다. 플레이어보다 소켓을 추적하여 플레이어를 쉽게 제거 할 수 있습니다.
code-jaff 2013-06-25

플레이어를 삭제 한 다음 연결을 해제하려면 어떻게해야합니까? 플레이어가 언제 연결을 끊을 지 어떻게 알 수 있습니까?.
Raggaer 2013-06-25

4
클라이언트의 이벤트가 'disconnect'대신 해야하지 'disconnected'않습니까?
Sherlock

1
OP의 원래 클라이언트 코드에서 @Sherlock은 연결이 끊긴 논리에 대해 서버 측을 트리거하는 사용자 지정 이벤트를 수신하려고 시도했습니다. '연결 해제'는 실제로 기본 제공 연결 해제 이벤트이지만 발생하는 문제에 직접적으로 기여하지는 않습니다.
Jon Church

답변:


171

좋아, 플레이어가 연결된 소켓이있는 이름 트랙으로 플레이어를 식별하는 대신. 다음과 같은 구현을 가질 수 있습니다.

섬기는 사람

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

이것이 다른 방식으로 생각하는 데 도움이되기를 바랍니다.


91
allClients.splice(i, 1)요소를 삭제하는 데 더 유용 합니다. delete allClients[i]배열 위치를 다음으로 설정합니다undefined
Yves

1
왜 작동하지만 이름 솔루션으로 사람 추적이 작동하지 않습니까?
sha1

이것은 나를 위해 작동하지 않습니다. 여기에 i-1 때마다 값을 얻었다. 무슨 일인지 말씀해 주시겠습니까?
Vinit Chouhan 2015

1
@VinitChouhan 아마도 실제 문제와는 별도의 질문을해야합니다.
code-jaff

값이 -1이면 존재하지 않는 소켓을 연결하려고한다는 의미입니다 (누군가 연결이 끊어졌지만 아직 allClients어레이 에 사용자를 등록하지 않았습니다 ). 나는 당신이 if (i === -1)return;그것을 연결하기 전에 그냥 돌아 오는 것이 좋습니다 .
Koen B.

23

@ sha1과 같은 사람들이 왜 OP의 코드가 작동하지 않는지 궁금해합니다.

서버 측에서 플레이어를 삭제하는 OP 로직은 DelPlayer이벤트 핸들러에 있으며,이 이벤트 ( DelPlayer) 를 발생시키는 코드 disconnected는 클라이언트의 이벤트 콜백 내부에 있습니다 .

disconnected이벤트 를 발생시키는 서버 측 코드 disconnect는 소켓 연결이 끊어 질 때 발생 하는 이벤트 콜백 내부에 있습니다. 소켓이 이미 연결이 끊어 졌으므로 disconnected이벤트가 클라이언트에 도달하지 않습니다.


수락 된 솔루션은 disconnect소켓이 연결 해제 될 때 실행되는 서버 측 에서 이벤트 로직을 실행 하므로 작동합니다.


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
그리고 베테랑의 설명과 코멘트가 포함 된 자세한 답변을 기대할 수 있겠지만, 코드 몇 개만으로 해결해야한다고 생각합니다
Cemal dec

내가 대답 작성 기억 해달라고, 당신은 질문이 있으면 알려 주시기
알렉산더 밀스를

1
사실 질문이 없습니다. 이것은 작성자에 대한 건설적인 비판 일뿐입니다. 저자는 댓글을 사용하고 설명을 추가하여 누구든지 (최소한) 당신을 괴롭히지 않고 당신의 예를 이해할 수 있도록합니다. 어쨌든 새해 복 많이 받으세요 ..
Cemal

0

또한 소켓 ID를 사용하여 이와 같이 플레이어 목록을 관리 할 수 ​​있습니다.

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)
  })
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.