Socket.io: La bonne façon pour un client de se reconnecter après que le serveur ait fait un socket.disconnect( true )

Créé le 9 mars 2016  ·  35Commentaires  ·  Source: socketio/socket.io

Serveur : node + 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 );

Client : 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' );
} );

Ce qui précède est simplifié mais c'est la base. La reconnexion fonctionne bien si je lance le client lorsque le serveur est en panne. Le client essaie de se connecter au serveur et lorsque je lance enfin le serveur, la connexion est établie.

À un moment donné, il peut arriver que le serveur décide de déconnecter le client, principalement parce qu'il s'est déconnecté en invalidant le jeton et qu'une requête sur la base de données lui dit de le faire, ou que le jeton d'authentification a expiré ou autre.

DANS cette circonstance, j'aimerais que le client restaure l'interrogation du serveur car l'utilisateur peut vouloir se reconnecter et il a le droit de se connecter à nouveau au serveur.

Si je rafraîchis la page (client) dans le navigateur, cela fonctionne bien mais c'est une solution laide.

Je pense que la cause est la propriété "Manager.skipReconnect" définie sur true après avoir fait déconnecter (), donc je demande quelle est la bonne façon de relancer une interrogation de reconnexion par le client après que le serveur a déconnecté un client.

J'ai trouvé des réponses sur stackoverflow à ce sujet, mais toutes ont échoué, toutes les choses à exécuter dans le client :

  • socket.io.reconnect();
  • socket.socket.reconnect(); // ??
  • socket = io.connect( ' http://127.0.0.1 :3000', ... // réappeler l'extrait de connexion semble une mauvaise idée

Pourriez-vous m'aider à ce sujet?

Merci

Commentaire le plus utile

Pour l'instant, j'ai géré de cette façon et cela semble être stable:

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

Tous les 35 commentaires

Pour l'instant, j'ai géré de cette façon et cela semble être stable:

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

En utilisant une approche similaire de :

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

Malheureusement, cela amène le socket à utiliser le protocole http, plutôt que des sockets Web.

Toujours à la recherche d'une bonne approche pour une connexion socket Web persistante.

Ai-je raté quelque chose ???

Également intéressé par une solution à cela.

socket.connect()
a fonctionné pour moi sur la version 1.5.1 . J'espère que cela pourra aider.

@sconway Pouvez-vous nous éclairer ? Un code peut-être?

Salut,

Avait la même question, trouvé cette solution, actuellement en test, semble être une solution robuste ou une solution de contournement robuste... (les deux sont fournis)

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

Pourrions-nous résoudre ce problème dans socket.io lui-même ?

J'ai mis à niveau vers la version 2.0.3 et ses paramètres de reconnexion automatique par défaut ont fonctionné, aucun problème ici.

Lorsque le serveur ou le client appelle la méthode disconnect(), le client détruit le socket, supprime tous les gestionnaires d'événements et le gestionnaire le supprime du tableau de connexion. Cela ne se produit pas lorsque la déconnexion est pour une autre raison.
Une excellente solution de contournement pourrait être de lire le paramètre de raison
.on('disconnect', reason => { if(reason === 'io server disconnect') { //you should renew token or do another important things before reconnecting socket.connect(); } });
Ou bien mieux vérifier si socket est toujours dans la liste de connexion du gestionnaire
.on('disconnect', () => { if(socket.io.connecting.indexOf(socket) === -1){ //you should renew token or do another important things before reconnecting socket.connect(); } })

Je l'ai fait comme @DrLightman et ça marche parfaitement !

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 c'est comme ça que je le fais et fonctionne parfaitement dans les navigateurs ou les applications Android/IOS
var io= new socketio.connect('http://192.168.43.79:3000',{'forceNew':true});

@pablodgonzalez j'ai la même question, votre solution fonctionne?

@programmerCs Oui, ça l'est. En production sans problèmes détectés.

Ce problème a résolu beaucoup de mes problèmes
Merci tout le monde

J'ai eu le même problème lorsque j'ai voulu forcer un client à actualiser son jeton car il a expiré alors qu'il était connecté au serveur.

J'ai fini par envoyer un événement au client à la place, lui demandant d'actualiser son jeton. Aucune socket ne se ferme en faisant cela, donc ça évite les problèmes et ça marche bien !

... maintenant il est temps de pousser ça vers la production ! :cold_sweat: :sourire:

Il semble que la solution la plus simple consiste à écouter l'événement « déconnecter » de l'émetteur et à appeler la fonction setTimeout(), mais qu'en est-il des événements que le client peut créer pendant qu'il est déconnecté du serveur ? On dirait qu'il doit toujours exécuter une vérification supplémentaire si la connexion est établie avant de diffuser une émission sur le client.

@qassa si vous avez besoin d'une confirmation sur l'émission, vous devez utiliser le paramètre de rappel. Au lieu de cela, si vous avez besoin de garantir la réception d'un événement, vous ne devez pas utiliser socket.io mais une bibliothèque/protocole de file d'attente tel que moustique/mqtt ou autre.
le setTimeout est une option mais une socket déconnectée (par le serveur ou le client) est une socket bientôt détruite. Donc, si vous avez besoin de garantir une reconnexion facile et rapide, pourquoi utiliser setTimeout si vous avez déjà l'instance de l'objet socket et pouvez appeler connect() ?

Quelqu'un du projet A VRAIMENT BESOIN DE DOCUMENTER ce...

Laissez-moi comprendre, le serveur déconnecte-t-il le client pour une raison spécifique ou en raison d'une perte de connexion réseau ? S'il ne s'agit que du réseau, Socketio (client) essaiera indéfiniment de se reconnecter ! , si configuré comme ceci io=new socketio(‘http://yourserver.com’, {'forceNew':true}); toute façon, il se reconnectera toujours, mais si vous mettez un écouteur pour se déconnecter du serveur, appelez simplement io.disconnect() sur le client

De : CxRes [mailto:[email protected]]
Envoyé : 01 février 2018 21:50
À : socketio/socket.io [email protected]
Cc : devyaz [email protected] ; Commentaire [email protected]
Objet : Re : [socketio/socket.io] La bonne façon pour un client de se reconnecter après que le serveur ait fait un socket.disconnect( true ) (#2476)

Quelqu'un du projet A VRAIMENT BESOIN DE DOCUMENTER ce...

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub https://github.com/socketio/socket.io/issues/2476#issuecomment-362381171 , ou coupez le fil https://github.com/notifications/unsubscribe-auth/ ATfQSQQ1LJ90E6FqsdmiMktpp2AdoLuxks5tQhVQgaJpZM4HsVs7 . https://github.com/notifications/beacon/ATfQSYqwkgtrHZk9FASNZUl69ps9ZYYCks5tQhVQgaJpZM4HsVs7.gif

@devyaz je t'aime

La documentation a été mise à jour avec la réponse de @pablodgonzalez : https://github.com/socketio/socket.io-client/commit/afb952d854e1d8728ce07b7c3a9f0dee2a61ef4e

Merci beaucoup!

Utiliser la version 0.8.3 de io.socket supprimer la nouvelle version 1.0.0

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

En utilisant une approche similaire de :

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

Malheureusement, cela amène le socket à utiliser le protocole http, plutôt que des sockets Web.

Toujours à la recherche d'une bonne approche pour une connexion socket Web persistante.

Ai-je raté quelque chose ???

utiliser wss://

En utilisant une approche similaire de :

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

Malheureusement, cela amène le socket à utiliser le protocole http, plutôt que des sockets Web.
Toujours à la recherche d'une bonne approche pour une connexion socket Web persistante.
Ai-je raté quelque chose ???

utiliser wss://

bonjour, mon frère.comment se peut-il que si vous utilisez simplement wss.il fonctionne comme une connexion de socket Web persistante, vous avez la même question à propos de la conservation et de la reconnaissance rapide avec ws sans interrogation.

Lorsque le serveur ou le client appelle la méthode disconnect(), le client détruit le socket, supprime tous les gestionnaires d'événements et le gestionnaire le supprime du tableau de connexion. Cela ne se produit pas lorsque la déconnexion est pour une autre raison.
Une excellente solution de contournement pourrait être de lire le paramètre de raison

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

Ou bien mieux vérifier si socket est toujours dans la liste de connexion du gestionnaire

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

Pouvez-vous expliquer pourquoi il est préférable de vérifier si le socket est toujours dans la liste de connexion du gestionnaire ? La doc mise à jour n'a pris que votre première solution qui consiste à vérifier la raison de la déconnexion. Merci.

Salut @emclab , juste parce que si dans une version plus récente les développeurs ajoutent une nouvelle raison, et pour votre cas n'est pas important "la raison", alors recherchez simplement le socket dans la liste des connexions. s'il n'est pas là, vous devez donc vous reconnecter manuellement.
Dans certains cas, il est important de connaître la raison, et c'est le cas le plus puissant, de lire et d'agir en conséquence, mais ce n'est peut-être pas le plus courant.
Avis de non-responsabilité : si vous optez pour la deuxième voie, vous n'êtes pas à l'abri des refactors ou de certains changements de mécanismes dans les nouvelles versions, donc ce n'est pas beaucoup mieux mais beaucoup plus simple.
Cordialement!

Je ne parviens pas à me déconnecter du socket dans l'application ionique. J'ai socket.on dans le constructeur de la page commune dans les fournisseurs. Je souhaite déconnecter socket dans une fonction sur le même fichier à partir duquel la déconnexion de l'application est appelée.

Mais j'arrive à débrancher la prise. Je suis multiple socket.on('event') sur plusieurs émissions dans l'application.
Quelqu'un peut m'aider?

Socket.disconnect() devrait faire l'affaire

Le lundi 11 novembre 2019 06:16 krunal9421, [email protected] a écrit :

Je ne parviens pas à me déconnecter du socket dans l'application ionique. j'ai
socket.on dans le constructeur de la page commune dans les fournisseurs. je veux
déconnecter socket dans une fonction sur le même fichier d'où l'application
la déconnexion est appelée.

Mais j'arrive à débrancher la prise. Je suis multiple socket.on('événement')
sur plusieurs émissions dans l'application.
Quelqu'un peut m'aider?

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASNI2K4DWOB4P2HPSATQTDMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63TNMVX228WHJNGO72TMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVX228WHJKDN
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AE35ASJPORGOSYQAEJEHHG3QTDMC7ANCNFSM4B5RLM5Q
.

@devyaz Je ne
J'ai partagé mon exemple de code avec ceci.
https://i.stack.imgur.com/wrIEv.png.

J'ai écrit du code dans un fichier commun.

Essayez-vous de vous déconnecter du côté serveur ou utilisateur ? c'est-à-dire que le serveur doit
déconnecter l'utilisateur. Parce que si le serveur perd le client, il déclenche une déconnexion
un événement. Mais le client peut se déconnecter du serveur en appelant
socket.disconnect

Le mercredi 20 novembre 2019 à 05:39 krunal9421, [email protected] a écrit :

@devyaz https://github.com/devyaz Je n'arrive pas à déconnecter la prise
en utilisant socket.disconnect().
J'ai partagé mon exemple de code avec ceci.
https://i.stack.imgur.com/wrIEv.png.

J'ai écrit du code dans un fichier commun.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASK4NY4SKG5JWSBDKCTQUSWNVA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LEQNMVXH58Zissue21GO ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AE35ASIFTISGTIAQQ7UKCJDQUSWNVANCNFSM4B5RLM5Q
.

en l'utilisant côté client.

Faites this.socketstatus.disconnect() dans votre fonction de déconnexion et je pense
vous devez supprimer la fonction ".on("connected",.....)"

Le vendredi 22 novembre 2019 11:50 krunal9421, [email protected] a écrit :

en l'utilisant côté client.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASJTREAYRMF4THBK3FDQU6TOLA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMCIWSW63LN5P5WWZHJEEEEKTNO5P5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMCIWSW63LNMVE-5WWZHJémissionLODNGO5P
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AE35ASJGKVGVUQNK454C63DQU6TOLANCNFSM4B5RLM5Q
.

Après avoir perdu la connexion, le socket se reconnecte au serveur. Après cela, il continue à afficher _io.socket.engineio.client.EngineIOException: xhr post error_ in Android .
La plupart des réponses de StackOverflow ne fonctionnent pas.
Je suis coincé avec ce problème T_T.... Aidez-moi s'il vous plaît !

J'essaie d'implémenter ce code dans mon wepapp node.js + javaScript mais lorsque le navigateur de mon téléphone est en arrière-plan, dans un onglet inactif ou un écran verrouillé, il est déconnecté après quelques minutes.

J'ai essayé de me reconnecter à un socket lorsqu'il est déconnecté (avec des réponses ping timeout ou transport closed ) mais c'est impossible. Est-ce un comportement normal sur les navigateurs téléphoniques ? car dans les navigateurs d'ordinateurs portables ou de bureau, cela fonctionne comme prévu.

Quelqu'un peut-il m'aider?

Merci

Salut @asiermusa mais en web, vous devez utiliser un web-worker pour éviter de suspendre le processus. Je sincèrement je ne sais pas si c'est suffisant pour y parvenir.

Tchin Tchin!

Cette page vous a été utile?
0 / 5 - 0 notes