Socket.io: por que socket.disconnect() no lado do cliente não dispara o evento de desconexão no servidor?

Criado em 4 nov. 2015  ·  23Comentários  ·  Fonte: socketio/socket.io

aqui está meu código:

lado do cliente

 var socket = io.connect('http://' + serverAddress ,{ reconnection: false, forceNew: true  }  );

 socket.emit('monitorAddedNotify' , { video: sourceVideo , socketId: socket.id});

 socket.on('disconnectThatSoc', function(){
    socket.disconnect();
});

lado do servidor:

  io.on('connection', function (socket) {
    console.log('a user connected');


    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 });

o método socket.disconnect() não funciona por quê?

Unable to reproduce

Comentários muito úteis

você é burro? você está esperando por uma emissão no cliente, mas nenhuma emissão no servidor. foda-se daqui

Todos 23 comentários

Pelo que testei, funciona bem. Como podemos reproduzir o problema?

Tente entrar na página e recarregue rapidamente pressionando várias vezes o botão F5.

Funciona bem para mim também.

Que navegador você usa? Estou usando o Firefox mais recente e quando recarrego rapidamente o bage "usuário desconectado" não funciona :disappointed:

Eu também tenho o problema. Nestas ações, desconexão, mas vem muito depois do navegador reiniciado.

Navegador: Chrome 55.0.2883.95 (64 bits)
socket.io: "^1.7.2"

Olá @ventaquil. Estou com o mesmo problema que o evento de desconexão não dispara ao segurar F5. Você superou isso?

@giathinh910 não é o evento disconnect disparado após um determinado atraso (que pode estar relacionado às opções pingTimeout / pingInterval , documentadas aqui )?

@darrachequesne Meu problema é o mesmo que @ventaquil descrito acima "Tente entrar na página e recarregue rapidamente pressionando várias vezes o botão F5". Normalmente, quando você atualiza uma conexão de soquete de página, dispara "desconectar" e "conectar" novamente. Conto com esses 2 eventos para atualizar os números de usuários online. No entanto, se a página recarregar rápido o suficiente, o "desconectar" não será acionado, o que fará com que algum id de soquete de usuário inexistente seja adicionado. Essas pessoas irreais serão removidas após o pingTimeout, é claro. Atualmente eu mudo a forma de salvar o socket id que mostrará apenas o usuário online, não o número do socket e o problema pode ser resolvido.

Eu lidei com este problema desta forma. Eu fiz um emissor de emissão no cliente que está chamando a pulsação no servidor.
socket.on("heartbeat", function() { // console.log('heartbeat called!'); hbeat[socket.id] = Date.now(); setTimeout(function() { var now = Date.now(); if (now - hbeat[socket.id] > 5000) { console.log('this socket id will be closed ' + socket.id); if (addedUser) { --onlineUsers; removeFromLobby(socket.id); try { // this is the most important part io.sockets.connected[socket.id].disconnect(); } catch (error) { console.log(error) } } } now = null; }, 6000); });

Eu encontrei esta função de código para chamar:

io.sockets.connected[socket.id].disconnect();

Isso ainda acontece. Não precisa ser F5/atualizar. Abrir uma aba e fechá-la rapidamente em um determinado estágio, faz com que a desconexão não seja acionada. É difícil de reproduzir porque os soquetes são muito rápidos, especialmente quando executados localmente. Percebi que abrir a aba em segundo plano e ter outras abas abertas ajudou a reproduzir o problema (localmente). Eu acho que este é um bug importante que deve ser corrigido.

Tenho o mesmo problema aqui. Isso está criando jogos fantasmas no meu servidor de jogos

Talvez para desconectar manualmente o cliente, você pode usar uma função com alguma emissão.
Não sei se isso vai ajudar, mas acho que consegui alguma coisa... Talvez...

Cliente :

function ManualSocketDisconnect() {
    socket.emit("manual-disconnection", socket.id);

    socket.close();

    console.log("Socket Closed. ");
}

Servidor :

io.on("connection", function(socket) {
    console.log("User " + socket.id + " Connected. ");

    socket.on("manual-disconnection", function(data) {
        console.log("User Manually Disconnected. \n\tTheir ID: " + data);
    });
});

Desculpe, mas provavelmente deixei alguns buracos no meu código. Não sou profissional. 🙁

Eu estou enfrentando o mesmo problema!
Estarei dando o exemplo em ReactJS-ExpressJS.

Aqui está a situação, que irá disparar o evento, e está encapsulada em componentWillUnmount() .

Estarei comparando dois eventos, que dispararei de componentWillUnmount()

  1. newMessage :- isso transmitirá a mensagem para uma sala específica
  2. disconnect :-(Esperava que funcionasse, mas não funciona) Este ouvinte de evento tem um retorno de chamada que será desconectado. Eu contive um console.log() apenas para confirmar se o retorno de chamada é atingido.

Agora vamos lá:-
Cliente:-

Estes eventos estão sendo acionados:-

  componentDidMount() {
    console.log(this.props)
    chat.emit('authenticate', {
      token: localStorage.getItem('auth'),
      refreshToken: localStorage.getItem('refresh'),
      projectId: this.props.projectId,
      userId: this.props.userId,
    });
    chat.on('newMessage', (messageData) => {
      console.log('------------newMessageReceived-------------');
      this.props.messageReceived({ messages: this.props.messages, messageData }, () => {
        console.log('callback');
        this.setState({
          messages: this.props.messages
        })
      })
      console.log(messageData);
    })
  }

O evento seguinte não dispara.

  componentWillUnmount() {
    chat.emit('disconnect','just disconnect);
  }

O evento a seguir será acionado. (apenas testando se o evento de mensagem normal é emitido)

  componentWillUnmount() {
    chat.emit('newMEssage', {
      messageHeader: {
        sender: {
          user: {
            id: this.props.userId,
            name: this.props.name
          }
        }
      },
      messageBody: 'hello',
    });
  }

Sem sorte

Servidor:-
Aqui está o código no backend expressJS

//A seguir initializeChatSocket é chamado em app.js

function initializeChatSocket(server) {
  projects.hasMany(projectTeam, { foreignKey: 'projectId' });

  const io = socketIO(server);
  const chat = io.of('/chat').on('connection', function (socket) {
    console.log(
      '----------------------------------------New Chat Connection Established-------------------------------------------------------------------------'
    );

    socket.auth = false;

    socket.on('authenticate', function (data) {
      console.log('\n\n\n\n', 'authenticate called', '\n\n\n\n', data, '\n\n\n');

      try {
        const dummyReq = {
          headers: {
            refreshtoken: data.refreshToken,
          },
        };
        console.log('\n\n\n\n', 'before verify', '\n\n\n\n');
        const userDetails = verifyJWTToken(dummyReq, data.token);
        console.log('\n\n\n\n', 'after verify', '\n\n\n\n');
        socket.userId = userDetails.userId;
        socket.projectId = data.projectId;

        projectTeam
          .findAll({
            where: {
              [Op.and]: {
                projectId: data.projectId,
                userId: data.userId,
              }
            }
          })
          .then(projects => {
            console.log('\n\n\n\n', JSON.stringify(projects), '\n\n\n\n');
            if (projects.length === 1) {
              socket.auth = true;
              socket.join(socket.projectId);
              console.log('User id:- ${userDetails.userId} linked to project id :- ${socket.projectId}');
            } else {
              console.log('User id:- ${userDetails.userId} not linked to project id :- ${socket.projectId}');
              throw { message: 'User not linked to project' };
            }
          });
      } catch (error) {
        console.log(String(error));

        socket.auth = false;
        socket.disconnect(String(error));
      }
    });

    socket.on('disconnectt', function() {
      console.log('Client Disconnecting'); // This is not being fired :/
      socket.removeAllListeners('newMessage');
      socket.removeAllListeners('disconnect');
      socket.removeAllListeners('authenticate');
      socket.removeAllListeners('connection');
      });

    socket.on('newMessage', async function (messageData) {
      console.log('-------------------------New Message----------------------', String(messageData));
      //TODO Save Message in Database

      try {
        socket.broadcast.to(socket.projectId).emit('newMessage', messageData);
        console.log('\n\n\n\n\n broadcast sent\n\n' + JSON.stringify(messageData) + '\n\n\n');
      } catch (error) {
        console.log('\n\n\n\n\n broadcast error\n\n\n\n\n');
        console.log(String(error));

        console.log(error);
        //TODO Handle Message Sending Error
      }
    });

  });
}

Isso é algum problema com o navegador ou outra coisa que eu preciso perguntar da comunidade stack-overflow?

@manjotsk Não tenho certeza se você já o corrigiu, mas no código do lado do servidor você está ouvindo disconnectt (observe o duplo t ), mas seu front-end está emitindo disconnect . Além disso, você provavelmente não deseja emitir disconnect , pois esse evento deve ser enviado de cliente para servidor quando o cliente se desconecta.

Eu tenho um código que depende do soquete emitindo o evento de desconexão para evitar ips duplicados - os usuários que recarregam meu aplicativo rapidamente são bloqueados porque a desconexão nunca é acionada!

@manjotsk Não tenho certeza se você já o corrigiu, mas no código do lado do servidor você está ouvindo disconnectt (observe o duplo t ), mas seu front-end está emitindo disconnect . Além disso, você provavelmente não deseja emitir disconnect , pois esse evento deve ser enviado de cliente para servidor quando o cliente se desconecta.
disconnectt era um alias impostor que eu estava usando! Obrigado por apontar. Vou verificar novamente com isso em ambos os lados. E, obviamente, a implementação estava errada! Eu tenho uma visão mais clara! Obrigado @nathanheffley 👍 :)

@manjotsk O quê?

e use apenas socket.once em vez de socket.on
"nível do cliente".
exemplo:
socket.on('conectar')
usar
socket.once('conectar'
.

mesmo aqui meu
socket.on("message") { (dataArray, socketAck) -> Void in

  if let data = dataArray.first as? Data{
    do{
      let objc = try JSONDecoder.init().decode(GetChatConversation.self, from: data)
      completionHandler(objc,nil)
    }
    catch let error{
      return completionHandler(nil,error.localizedDescription)
    }
  }else{
    completionHandler(nil,"Cannot cast Array of Any to Data")
  }
}

não retorne o callback se alguém souber me diga

você é burro? você está esperando por uma emissão no cliente, mas nenhuma emissão no servidor. foda-se daqui

Isso é uma verdadeira energia negativa, Ehsan666x.

Eu lidei com este problema desta forma. Eu fiz um emissor de emissão no cliente que está chamando a pulsação no servidor.
hbeat[socket.id] = Date.now();

Gostaria de saber qual hbeat deve ser enviado do lado do cliente?

Em vez de socket.disconnect() ou socket.emit('disconnect') tente socket.close(); no lado do cliente e isso deve acionar o evento 'disconnect' no lado do servidor. Funcionou para mim.

Esta página foi útil?
0 / 5 - 0 avaliações