web-dev-qa-db-fra.com

Méthode recommandée pour reconnecter le client .NET SignalR 2.0 au concentrateur de serveur

J'utilise SignalR 2.0 avec le client .NET dans une application mobile et je dois donc gérer différents types de déconnexion. Parfois, le client SignalR se reconnecte sans mon aide - et parfois je dois me reconnecter en appelant à nouveau HubConnection.Start (). (Puisque SignalR se reconnecte automatiquement comme par magie de temps en temps, je me demande s'il me manque une fonction ou un paramètre de configuration)

Quel est le meilleur moyen de configurer un client qui se reconnecte automatiquement? J'ai vu des exemples javascript qui gèrent l'événement Closed (), puis Connect après un délai de n secondes. Y a-t-il une approche recommandée? 

J'ai lu la documentation et plusieurs articles sur la durée de vie des connexions SignalR, mais je ne comprends toujours pas comment gérer la reconnexion du client.

Je vous remercie!

69
Ender2050

J'ai finalement compris cela. Voici ce que j'ai appris depuis le début de cette question:

Arrière-plan: Nous sommes en train de créer une application iOS à l'aide de Xamarin/Monotouch et du client .NET SignalR 2.0.3. Nous utilisons les protocoles SignalR par défaut - et il semble utiliser SSE au lieu de sockets Web. Je ne sais pas encore s'il est possible d'utiliser des sockets Web avec Xamarin/Monotouch. Tout est hébergé sur les sites Web Azure. 

Nous avions besoin de l'application pour nous reconnecter rapidement à notre serveur SignalR, mais nous avions toujours des problèmes lorsque la connexion ne se reconnectait pas d'elle-même - ou que la reconnexion prenait exactement 30 secondes (en raison d'un délai de protocole sous-jacent).

Nous avons finalement testé trois scénarios:

Scénario A - connexion au premier chargement de l'application. Cela a fonctionné parfaitement dès le premier jour. La connexion se termine en moins de 0,25 seconde, même sur des connexions mobiles 3G. (en supposant que la radio est déjà allumée)

Scénario B - Reconnexion au serveur SignalR après que l'application était inactive/fermée pendant 30 secondes. Dans ce scénario, le client SignalR se reconnectera au serveur seul sans travail particulier - mais il semble attendre exactement 30 secondes avant de tenter de se reconnecter. (beaucoup trop lent pour notre application)

Pendant cette période d'attente de 30 secondes, nous avons essayé d'appeler HubConnection.Start (), ce qui n'a eu aucun effet. Et appeler HubConnection.Stop () prend également 30 secondes. J'ai trouvé un bogue associé sur le site de SignalR qui semble être résolu , mais nous rencontrons toujours le même problème dans la v2.0.3.

Scénario C - vous reconnecter au serveur SignalR après que l'application était inactive/fermée pendant 120 secondes ou plus. Dans ce scénario, le protocole de transport SignalR a déjà expiré afin que le client ne se reconnecte jamais automatiquement. Cela explique pourquoi le client se reconnectait parfois mais pas toujours seul. La bonne nouvelle est que l'appel à HubConnection.Start () fonctionne presque instantanément comme le scénario A.

Il m'a donc fallu un certain temps pour comprendre que les conditions de reconnexion étaient différentes selon que l'application était fermée pendant 30 secondes ou plus de 120 secondes. Et bien que les journaux de traçage de SignalR illustrent ce qui se passe avec le protocole sous-jacent, je ne pense pas qu'il soit possible de gérer les événements de niveau de transport dans le code. (l'événement Closed () se déclenche après 30 secondes dans le scénario B, instantanément dans le scénario C; la propriété State indique "Connecté" pendant ces périodes d'attente de reconnexion; aucun autre événement ni aucune méthode pertinents).

Solution: La solution est évidente. Nous n'attendons pas que SignalR fasse sa magie de reconnexion. Au lieu de cela, lorsque l'application est activée ou lorsque la connexion réseau du téléphone est restaurée, nous ne faisons que nettoyer les événements et dé-référencer HubConnection. ) et créer une nouvelle instance. Maintenant tout fonctionne bien. Pour une raison quelconque, j'ai pensé que nous devrions réutiliser une connexion persistante et vous reconnecter au lieu de simplement créer une nouvelle instance. 

61
Ender2050

Configurer une minuterie sur l'événement déconnecté pour une tentative de reconnexion automatique est la seule méthode à ma connaissance.

En javascript c'est fait comme ça:

$.connection.hub.disconnected(function() {
   setTimeout(function() {
       $.connection.hub.start();
   }, 5000); // Restart connection after 5 seconds.
});

C'est l'approche recommandée dans la documentation:

http://www.asp.net/signalr/overview/signalr-20/hubs-api/handling-connection-lifetime-events#clientdisconnect

37

Depuis le PO demandant un client .NET (implémentation Winform ci-dessous), 

private async Task<bool> ConnectToSignalRServer()
{
    bool connected = false;
    try
    {
        Connection = new HubConnection("server url");
        Hub = Connection.CreateHubProxy("MyHub");
        await Connection.Start();

        //See @Oran Dennison's comment on @KingOfHypocrites's answer
        if (Connection.State == ConnectionState.Connected)
        {
            connected = true;
            Connection.Closed += Connection_Closed;
        }
        return connected;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error");
        return false;
    }
}

private async void Connection_Closed()
{
    if(!IsFormClosed) // A global variable being set in "Form_closing" event of Form, check if form not closed explicitly to prevent a possible deadlock.
    {
        // specify a retry duration
        TimeSpan retryDuration = TimeSpan.FromSeconds(30);
        DateTime retryTill = DateTime.UtcNow.Add(retryDuration);

        while (DateTime.UtcNow < retryTill)
        {
            bool connected = await ConnectToSignalRServer();
            if (connected)
                return;
        }
        Console.WriteLine("Connection closed")
    }
}
11
ibubi
Multiple query string
self.hubConnection = $.hubConnection();
self.hubConnection.qs = { param1: value, param2: value };

de:

Signalr - Impossible de lire les chaînes de requête sur le serveur

0
AShah