Socket.io: A maneira certa para um cliente se reconectar depois que o servidor faz um socket.disconnect (true)

Criado em 9 mar. 2016  ·  35Comentários  ·  Fonte: socketio/socket.io

Servidor : nó + socket.io

var io = require( 'socket.io' )( 3000 );

io.on( 'connection', function ( socket ) ...

// at some point if client auth fails, server may kick him out:

socket.disconnect( true );

Cliente : html / js + socket.io 1.4.5

socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: 99999
} );

socket.on( 'connect', function () {
    console.log( 'connected to server' );
} );

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

O acima é simplificado, mas essa é a base. A reconexão funciona bem se eu iniciar o cliente quando o servidor estiver inativo. O cliente tenta se conectar ao servidor e quando eu finalmente ligo o servidor, a conexão é estabelecida.

Em algum momento pode acontecer que o servidor decida desconectar o cliente, principalmente porque ele se desconectou invalidando o token e uma consulta no banco de dados diz para fazer isso, ou o token de autenticação expirou ou algo assim.

Nesta circunstância, eu gostaria de restaurar a sondagem do servidor pelo cliente porque o usuário pode querer fazer o login novamente e ele tem o direito de se conectar novamente ao servidor.

Se eu atualizar a página (cliente) no navegador, ele funciona bem, mas é uma solução feia.

Acho que a causa é a propriedade "Manager.skipReconnect" definida como true após desconectar (), então estou perguntando qual é a maneira correta de reiniciar uma pesquisa de reconexão pelo cliente depois que o servidor desconecta um cliente.

Encontrei algumas respostas no stackoverflow sobre isso, mas todas não tiveram sucesso, todas as coisas deveriam ser executadas no cliente:

  • socket.io.reconnect ();
  • socket.socket.reconnect (); // ??
  • socket = io.connect (' http://127.0.0.1 : 3000', ... // reinvocar o snippet de conexão parece uma má ideia

Você poderia me ajudar sobre este assunto?

Obrigado

Comentários muito úteis

Por enquanto, consegui assim e parece estável:

Cliente :

var app = {
...
socket: null,
connect: function() {
  var self = this;
  if( self.socket ) {
    self.socket.destroy();
    delete self.socket;
    self.socket = null;
  }
  this.socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );
  this.socket.on( 'connect', function () {
    console.log( 'connected to server' );
  } );
  this.socket.on( 'disconnect', function () {
    console.log( 'disconnected from server' );
    window.setTimeout( 'app.connect()', 5000 );
  } );
}
...
} // var app

Todos 35 comentários

Por enquanto, consegui assim e parece estável:

Cliente :

var app = {
...
socket: null,
connect: function() {
  var self = this;
  if( self.socket ) {
    self.socket.destroy();
    delete self.socket;
    self.socket = null;
  }
  this.socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );
  this.socket.on( 'connect', function () {
    console.log( 'connected to server' );
  } );
  this.socket.on( 'disconnect', function () {
    console.log( 'disconnected from server' );
    window.setTimeout( 'app.connect()', 5000 );
  } );
}
...
} // var app

Usando uma abordagem semelhante de:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Infelizmente, isso faz com que o soquete use o protocolo http, em vez de soquetes da web.

Ainda estou procurando uma boa abordagem para uma conexão persistente de soquete da web.

Eu perdi alguma coisa ???

Também interessado em uma solução para isso.

socket.connect()
funcionou para mim na versão 1.5.1. Espero que ajude.

@sconway Você pode nos esclarecer? Qualquer código pode ser?

Olá,

Tive a mesma pergunta, encontrei esta solução, atualmente em teste, parece ser uma solução robusta ou uma solução alternativa robusta ... (ambos são fornecidos)

http://stackoverflow.com/questions/10437584/socket-io-reconnect

Podemos consertar isso no próprio socket.io?

Eu atualizei para a versão 2.0.3 e suas configurações padrão de reconexão automática funcionaram, sem problemas aqui.

Quando o servidor ou o cliente chamam o método disconnect (), o cliente destrói o soquete, exclui todos os manipuladores de eventos e o gerenciador o remove do array de conexão. Isso não ocorrerá quando a desconexão for por outro motivo.
Uma ótima solução poderia ser ler o parâmetro de razão
.on('disconnect', reason => { if(reason === 'io server disconnect') { //you should renew token or do another important things before reconnecting socket.connect(); } });
Ou muito melhor verificar se o soquete ainda está na lista de conexão do gerenciador
.on('disconnect', () => { if(socket.io.connecting.indexOf(socket) === -1){ //you should renew token or do another important things before reconnecting socket.connect(); } })

Fiz como @DrLightman e

var WebSocketServer = {
    isConnected: false,
    socket: null,
    interval: null,
    connect() {
        if (this.socket) {
            this.socket.destroy();
            delete this.socket;
            this.socket = null;
        }
        this.socket = io.connect('http://localhost:9010', {
            reconnection: false
        });
        this.socket.on('connect', () => {
            this.isConnected = true;
            this.socket.emit('authentication', { user_id: 2751, token: "abc" });
            this.socket.on('authenticated', function() {

            });
        });

        this.socket.on('disconnect', () => {
            this.isConnected = false;
            this.interval = window.setInterval(() => {
                if (this.isConnected) {
                    clearInterval(this.interval);
                    this.interval = null;
                    return;
                }
                WebSocketServer.connect()
            }, 5000);
        });

        return this.socket;
    }
}

var socket = WebSocketServer.connect();

@DrLightman é assim que eu faço e funciona perfeitamente em navegadores ou aplicativos Android / IOS
var io= new socketio.connect('http://192.168.43.79:3000',{'forceNew':true});

@pablodgonzalez eu tenho a mesma pergunta, sua solução funcionou?

@programmerCs Sim, é. Em produção sem problemas detectados.

Este problema esclareceu muitos dos meus problemas
Obrigado a todos

Tive o mesmo problema quando quis forçar um cliente a atualizar seu token porque ele expirou enquanto estava conectado ao servidor.

Em vez disso, acabei enviando um evento para o cliente, pedindo a ele para atualizar o token. Nenhum soquete é fechado com isso, evita problemas e funciona bem!

... agora é hora de colocar isso em produção! : cold_sweat:: smirk:

Parece que a solução mais simples é ouvir o evento 'desconectar' do emissor e chamar a função setTimeout (), mas e os eventos que o cliente pode criar enquanto está sendo desconectado do servidor? Parece que ele sempre precisa executar uma verificação adicional se a conexão foi estabelecida antes de transmitir qualquer emissão no cliente.

@qassa se você precisar de alguma confirmação sobre emit, você deve usar o parâmetro callback. Em vez disso, se você precisar garantir a recepção de um evento, não deve usar socket.io, mas alguma biblioteca / protocolo de fila, como mosquito / mqtt ou qualquer outro.
o setTimeout é uma opção, mas um soquete desconectado (pelo servidor ou pelo cliente) é um soquete logo destruído. Portanto, se você precisa garantir uma reconexão fácil e rápida, por que usar setTimeout se você ainda tem a instância do objeto socket e pode chamar connect ()?

Alguém do projeto REALMENTE PRECISA DOCUMENTAR isso ...

Deixe-me ver se entendi, o servidor desconecta o cliente por um motivo específico ou devido à perda de conexão de rede? Se for apenas uma rede, o Socketio (cliente) tentará se reconectar indefinidamente! , se configurado assim io=new socketio(‘http://yourserver.com’, {'forceNew':true}); qualquer forma, ele ainda se reconectará, mas se você colocar um listerner para desconectar do servidor, simplesmente chame io.disconnect() no cliente

De: CxRes [mailto: [email protected]]
Enviado: 01 de fevereiro de 2018 21:50
Para: socketio / socket.io [email protected]
Cc: devyaz [email protected] ; Comentário [email protected]
Assunto: Re: [socketio / socket.io] A maneira certa para um cliente se reconectar depois que o servidor faz um socket.disconnect (true) (# 2476)

Alguém do projeto REALMENTE PRECISA DOCUMENTAR isso ...

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/socketio/socket.io/issues/2476#issuecomment-362381171 ou ignore o tópico https://github.com/notifications/unsubscribe-auth/ ATfQSQQ1LJ90E6FqsdmiMktpp2AdoLuxks5tQhVQgaJpZM4HsVs7 . https://github.com/notifications/beacon/ATfQSYqwkgtrHZk9FASNZUl69ps9ZYYCks5tQhVQgaJpZM4HsVs7.gif

@devyaz eu te amo

A documentação foi atualizada com a resposta de @pablodgonzalez : https://github.com/socketio/socket.io-client/commit/afb952d854e1d8728ce07b7c3a9f0dee2a61ef4e

Muito obrigado!

Use a versão 0.8.3 de io.socket remova a nova versão 1.0.0

compile('io.socket:socket.io-client:0.8.3') {
    exclude group: 'org.json', module: 'json'
}

Usando uma abordagem semelhante de:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Infelizmente, isso faz com que o soquete use o protocolo http, em vez de soquetes da web.

Ainda estou procurando uma boa abordagem para uma conexão persistente de soquete da web.

Eu perdi alguma coisa ???

use wss: //

Usando uma abordagem semelhante de:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Infelizmente, isso faz com que o soquete use o protocolo http, em vez de soquetes da web.
Ainda estou procurando uma boa abordagem para uma conexão persistente de soquete da web.
Eu perdi alguma coisa ???

use wss: //

Olá, bro.how pode ser que se apenas usar wss.it apenas funcionar como conexão de socket web persistente, tenho a mesma dúvida sobre apenas manter e reconectar rapidamente com ws sem polling.

Quando o servidor ou o cliente chamam o método disconnect (), o cliente destrói o soquete, exclui todos os manipuladores de eventos e o gerenciador o remove do array de conexão. Isso não ocorrerá quando a desconexão for por outro motivo.
Uma ótima solução poderia ser ler o parâmetro de razão

.on('disconnect', reason => { 
  if(reason === 'io server disconnect') {
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
});

Ou muito melhor verificar se o soquete ainda está na lista de conexão do gerenciador

.on('disconnect',  () => {
  if(socket.io.connecting.indexOf(socket) === -1){
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
})

Você pode explicar por que é melhor verificar se o soquete ainda está na lista de conexão do gerenciador? O documento atualizado levou apenas a sua primeira solução, que é verificar o motivo da desconexão. Obrigado.

Olá @emclab , só porque se na versão mais recente os desenvolvedores adicionarem algum novo motivo, e para o seu caso não for importante "o motivo" então é só procurar o soquete na lista de conexões. se não estiver lá, você deve reconectar manualmente.
Em alguns casos é importante saber o motivo, e é o caso mais poderoso, leia e aja de acordo, mas talvez não seja o mais comum.
Isenção de responsabilidade: se você escolher o segundo caminho, não estará seguro de refatores ou de algumas mudanças nos mecanismos em versões mais recentes, portanto, não é muito melhor, mas muito mais simples.
Saudações!

Não consigo conectar a conexão do soquete à aplicação iônica. Eu tenho socket.on no construtor de página comum em provedores. Quero desconectar o soquete em uma função no mesmo arquivo de onde o logout do aplicativo é chamado.

Mas consigo desconectar o soquete. Eu sou vários socket.on ('evento') em vários emitem no aplicativo.
Alguém pode me ajudar?

Socket.disconnect () deve servir

Na segunda-feira, 11 de novembro de 2019, 06:16 krunal9421, notificaçõ[email protected] escreveu:

Não consigo conectar a conexão do soquete à aplicação iônica. eu tenho
socket.on no construtor da página comum em provedores. eu quero
desconecte o soquete em uma função no mesmo arquivo de onde o aplicativo
logout é chamado.

Mas consigo desconectar o soquete. Eu sou múltiplo socket.on ('evento')
em vários emitem no aplicativo.
Alguém pode me ajudar?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASNI2K4DWOB4P2HPSATQTDMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDVTS3A#issuecomment-552286572 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AE35ASJPORGOSYQAEJEHHG3QTDMC7ANCNFSM4B5RLM5Q
.

@devyaz Não consigo desconectar o soquete usando socket.disconnect ().
Estou compartilhando meu código de exemplo com isso.
https://i.stack.imgur.com/wrIEv.png.

Eu escrevi o código em um arquivo comum.

Você está tentando se desconectar do servidor ou do usuário? ou seja, o servidor deve
desconectar usuário. Porque se o servidor perder o cliente, ele dispara uma desconexão
evento. Mas o cliente pode se desconectar do servidor chamando
socket.disconnect

Na quarta-feira, 20 de novembro de 2019, 05:39 krunal9421, notificaçõ[email protected] escreveu:

@devyaz https://github.com/devyaz Não consigo desconectar o soquete
usando socket.disconnect ().
Estou compartilhando meu código de exemplo com isso.
https://i.stack.imgur.com/wrIEv.png.

Eu escrevi o código em um arquivo comum.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASK4NY4SKG5JWSBDKCTQUSWNVA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEQS5AI#issuecomment-555822721 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AE35ASIFTISGTIAQQ7UKCJDQUSWNVANCNFSM4B5RLM5Q
.

usando isso no lado do cliente.

Faça this.socketstatus.disconnect() em sua função de logout e eu acho
você deve remover a função ".on (" conectado ", .....)"

Na sexta-feira, 22 de novembro de 2019, 11h50 krunal9421, notificaçõ[email protected] escreveu:

usando isso no lado do cliente.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASJTREAYRMF4THBK3FDQU6TOLA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEE5EHCI#issuecomment-557466505 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AE35ASJGKVGVUQNK454C63DQU6TOLANCNFSM4B5RLM5Q
.

Depois de perder a conexão, o soquete se reconecta ao servidor. Depois disso, ele continua mostrando _io.socket.engineio.client.EngineIOException: xhr post error_ no Android .
A maioria das respostas do StackOverflow não funciona.
Estou preso com esse problema T_T .... Me ajude, por favor!

Estou tentando implementar este código no meu node.js + javaScript wepapp, mas quando o navegador do meu telefone está em segundo plano, em uma guia inativa ou tela bloqueada, ele é desconectado após alguns minutos.

Tentei reconectar a um soquete quando ele está desconectado (com ping timeout ou transport closed respostas), mas é impossível. Este é um comportamento normal em navegadores de telefone? porque em navegadores de laptop ou desktop funciona como esperado.

Alguém pode me ajudar?

Obrigado

Olá @asiermusa, mas na web você deve usar um web-worker para evitar a suspensão do processo. Sinceramente não sei se é o suficiente para isso.

Felicidades!

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