web-dev-qa-db-fra.com

connexion websocket fermant automatiquement

Je construis une application dans Java qui a un serveur Websocket intégré basé sur une jetée. Le client est l'implémentation Websocket par défaut dans Google Chrome. Tout fonctionne correctement, sauf s'il n'y a pas de transfert entre serveur et client après un certain temps, la connexion est fermée.Je ne sais pas qui ferme la connexion: le serveur Jetty ou le navigateur chrome.

Je pense que la solution à ce problème consiste à envoyer un message toutes les x secondes, mais je suis ouvert à de meilleures solutions.

SO ... mes questions sont:

  1. Est-ce quelque chose que le protocole websocket requiert et dans ce cas le chrome ferme ma connexion?)

  2. Est-ce quelque chose qui est plus lié à la jetée et qui a plus ou moins à faire avec le protocole websocket? Dans ce cas, comment puis-je désactiver ceci dans la jetée?

  3. Y a-t-il un autre problème ??

Merci

PDATE: même si j'envoie un message/seconde, la connexion est fermée

66
Doua Beri

En réponse à votre troisième question: votre client veut quand même pouvoir faire face à des problèmes de réseau temporaires, par exemple. Supposons que l'utilisateur ferme son ordinateur portable entre les réunions qui l'hibernent ou que le réseau s'arrête tout simplement temporairement.

La solution consiste à écouter les événements onclose sur le client de socket Web et, s’ils se produisent, à définir un délai d’expiration du côté client permettant de rouvrir la connexion, par exemple en une seconde:

function setupWebSocket(){
    this.ws = new WebSocket('wss://Host:port/path');
    this.ws.onerror = ...;
    this.ws.onopen = ...;
    this.ws.onmessage = ...;
    this.ws.onclose = function(){
        setTimeout(setupWebSocket, 1000);
    };
}
38
Ant Kutschera

Vous devez envoyer des messages ping de temps en temps. Je pense que le délai d'attente par défaut est de 300 secondes. Envoi d’un cadre websocket ping/pong à partir du navigateur

15
Tarek Zeineddine

J'ai trouvé une autre solution, plutôt rapide et sale. Si vous utilisez l'approche de bas niveau pour implémenter WebSocket et que vous implémentez vous-même la méthode onOpen, vous recevez un objet implémentant le WebSocket.Connection interface. Cet objet a une méthode setMaxIdleTime que vous pouvez ajuster.

9
LeoR

Vous pouvez en fait définir l'intervalle de délai d'attente lors de la configuration côté serveur Jetty à l'aide de l'instance WebSocketServletFactory. Par exemple:

        WebSocketHandler wsHandler = new WebSocketHandler()
        {
            @Override
            public void configure(WebSocketServletFactory factory)
            {
                factory.getPolicy().setIdleTimeout(1500);
                factory.register(MyWebSocketAdapter.class);
                ...
            }
        }
7
user3499459

Je viens de trouver la solution à cela pour moi-même. Ce que vous voulez définir est le maxIdleTime de WebSocketServlet, en millis. Comment faire cela dépend de la configuration de votre servlet. Avec Guice ServletModule, vous pouvez faire quelque chose comme ceci pendant 10 heures:

serve("ws").with(MyWSServlet.class, 
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});

Tout ce que <0 correspond à un temps d'inactivité infini, je crois.

4
AkaZn

Je crois que c'est un problème de jetée. Je n'ai vu aucun navigateur fermer les connexions WebSocket pour cause d'inactivité, ni rencontrer d'autres serveurs WebSocket pour lesquels les connexions WebSocket ont expiré.

Jetty est (était) principalement axée sur la création de servlets d'application basés sur HTTP. Dans ce contexte, les connexions HTTP doivent être nettoyées de manière assez agressive et HTTP n'a pas été conçu pour les connexions à longue durée de vie; il est donc raisonnable de disposer d'un délai d'attente court par défaut.

Je n'ai pas vu le problème précis que vous avez décrit (fermeture même après activité), mais je vois des connexions WebSocket fermées après 30 secondes d'inactivité. Il est possible que dans les anciennes versions de Jetty ou dans la version actuelle pour une autre raison, le minuteur ne soit pas réinitialisé par l'activité de WebSocket. Je contourne cela en utilisant la méthode setMaxIdleTime sur mon objet BlockingChannelConnector pour définir la valeur de délai d'attente sur Integer MAX_VALUE.

3
kanaka

Voici un exemple sur la façon de configurer le délai d'attente Websocket de Jetty (le coupable le plus probable) à l'aide de WebSocketServlet (en scala, désolé, mais la syntaxe est sensiblement la même).

import javax.servlet.annotation.WebServlet
import org.Eclipse.jetty.websocket.servlet.{WebSocketServletFactory, WebSocketServlet}

@WebServlet(name = "WebSocket Servlet")
class WebsocketServlet extends WebSocketServlet {
  override def configure(factory: WebSocketServletFactory): Unit = {
    factory.getPolicy.setIdleTimeout(1000 * 3600)
    factory.register(classOf[ClientWebsocket])
  }
}
2
user1338062

Je pense que le délai d'attente que vous rencontrez fait en réalité partie de TCP/IP et que la solution consiste simplement à envoyer des messages vides de temps en temps.

2
David Grayson

J'ai une expérience similaire et je pense que c'est peut-être le navigateur qui raccourcit la session. J'ai également défini maxIdleTimeout, mais la session est abandonnée malgré tout. Pour moi, il semblerait que ce soit le client (le navigateur) qui arrête la session, puis raccroche.

Je ne sais pas comment contourner le problème.

1
AndersW