2014-05-20 12 views
6

Setup:SignalR cliente viene ricollegato dopo Owin riavvio, ma il messaggio non è pubblicato

  1. SignalRServer console app: Microsoft.AspNet.SignalR.SelfHost v2.0.3
  2. SignalRClient console app: Microsoft .AspNet.SignalR.Client v2.0.3
  3. .NET 4.5.1

faccio la seguente:

  1. Hit entrare in cliente, viene ricevuto un messaggio sul server e sul client di nuovo
  2. Smaltire il server premendo un tasto qualsiasi della console del server
  3. Riavviare il server di un qualsiasi tasto nella console del server
  4. client viene ricollegato
  5. Hit entrare sul client, il messaggio viene ricevuto sul server, ma mai raggiunge di nuovo il cliente

Mi aspetto che il messaggio venga nuovamente ricevuto dal cliente. Sospetto che abbia qualcosa a che fare con l'auto-hosting, dal momento che ho provato a eseguire il client sullo stesso hub in un'applicazione Web che esegue IIS con successo.

Qualche idea?

Aggiornamento: se il processo della console del server viene interrotto e riavviato, è in grado di riconnettersi e recuperare nuovamente i messaggi.

codice Server

using System; 
using System.Threading.Tasks; 
using Microsoft.AspNet.SignalR; 
using Microsoft.Owin.Hosting; 
using Owin; 

namespace SignalRServer 
{ 
    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      const string url = "http://localhost:8081"; 

      while (true) 
      { 
       using (WebApp.Start<Startup>(url)) 
       { 
        Console.WriteLine("Server running on {0}. Hit any key to stop.", url); 
        Console.ReadLine(); 
       } 

       Console.WriteLine("Server stopped"); 

       Console.WriteLine("Hit any key to restart, Esc to exit"); 

       ConsoleKeyInfo ki = Console.ReadKey(true); 

       if (ki.Key == ConsoleKey.Escape) 
        return; 
      } 
     } 
    } 

    public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      app.MapSignalR(); 
     } 
    } 

    public class AuthenticationHub : Hub 
    { 
     public void BroadcastMessageToAll(string message) 
     { 
      Clients.All.sendMessageToClient(message); 
      Console.WriteLine("sendMessageToClient: " + message); 
     } 

     public override Task OnConnected() 
     { 
      Console.WriteLine("OnConnected " + Context.ConnectionId); 
      return base.OnConnected(); 
     } 

     public override Task OnReconnected() 
     { 
      Console.WriteLine("OnReconnected " + Context.ConnectionId); 
      return base.OnReconnected(); 
     } 

     public override Task OnDisconnected() 
     { 
      Console.WriteLine("OnDisconnected " + Context.ConnectionId); 
      return base.OnReconnected(); 
     } 
    } 
} 

Codice cliente

using System; 
using Microsoft.AspNet.SignalR.Client; 

namespace SignalRClient 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      while (true) 
      { 
       var hubConnection = new HubConnection("http://localhost:8081/signalr/hubs"); 

       hubConnection.Closed +=() => Console.WriteLine("Closed"); 
       hubConnection.StateChanged += e => Console.WriteLine("StateChanged: " + e.OldState + " " + e.NewState); 
       var hubProxy = hubConnection.CreateHubProxy("AuthenticationHub"); 

       hubProxy.On<string>("sendMessageToClient", 
        info => Console.WriteLine("sendMessageToClient received: " + info)); 
       hubConnection.Start(); 

       Console.WriteLine("Client started - hit Enter to send a message - ESC to stop"); 

       Console.ReadKey(); 

       while (true) 
       { 
        var keyInfo = Console.ReadKey(true); 

        if (keyInfo.Key == ConsoleKey.Escape) 
         break; 

        var message = "Console client : " + DateTime.Now.ToString("HH:mm:ss-fff"); 
        hubProxy.Invoke("BroadcastMessageToAll", message); 
        Console.WriteLine("Client sent BroadcastMessageToAll: " + message); 
       } 

       Console.WriteLine("Client stopping"); 

       hubConnection.Stop(); 

       Console.WriteLine("Client stopped - enter any key start again"); 
       Console.ReadLine(); 
      } 
     } 
    } 
} 
+0

Vorrei poter aiutare di più, ma ho copiato il server e il codice del client letteralmente in due console progetti di app. Dopo aver installato i pacchetti NuGet necessari, sono stato in grado di riavviare l'app del server, fare in modo che il client si ricolleghi automaticamente e quindi continuare a inviare e ricevere messaggi in seguito. – halter73

+0

Ho aggiornato i passaggi da riprodurre per essere più precisi. È necessario riavviare l'app della console del server stessa, ma l'app del server SignalR stessa. – Stian

risposta

5

Il team SignalR mi ha segnalato la soluzione: Per impostazione predefinita SignalR usa GlobalHost, che è un resolver Singleton. Quando disposto, non tornerà mai più.

Quando si crea la configurazione per l'hub, si dovrebbe passare inn un nuovo risolutore delle dipendenze:

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var hubConfiguration = new HubConfiguration {Resolver = new DefaultDependencyResolver()}; 
     app.MapSignalR(hubConfiguration); 
    } 
} 
0

mi ha diversi problemi simili con SignalR (non exacly nello stesso scenario).

Il problema si è verificato in genere nel modello di comunicazione request_from_server-> client-> response_to_server. Quando ho provato a chiamare Invoke nel codice client (per inviare una risposta al server) direttamente nella procedura di ricezione, ho ottenuto un comportamento strano (attese infinite, strani effetti collaterali, ecc.).

La soluzione era dividere il processo in due thread. Uno per ricevere messaggi dal server al ConcurrentQueue locale.Il secondo thread recupera i messaggi dalla coda, li elabora e invia le risposte al server (per Invoke). Ora SignalR funziona come previsto.

Questo problema è stato probabilmente causato dal tentativo di inviare la risposta PRIMA che la procedura di ricezione sia stata completata. Questo non succede nel solito client-> server-> modello di comunicazione client.

1

La risposta di Stian è ottima. Ma se è necessario utilizzare metodi statici definiti in GlobalHost, è necessario assegnare il resolver di dipendenza a GlobalHost.

le seguenti opere per me:

public void Configuration(IAppBuilder app) 
{ 
    .... Other configurations .... 
    GlobalHost.DependencyResolver = new DefaultDependencyResolver(); 
    app.MapSignalR(); 
} 

ho definito contesto hub in questo modo:

public sealed class RemoteAdminHub : Hub 
{ 
    #region Properties 

    /// <summary> 
    /// Gets the SignalR Hub context. 
    /// </summary> 
    public static IHubContext HubContext 
    { 
     get 
     { 
      return GlobalHost.ConnectionManager.GetHubContext<RemoteAdminHub>(); 
     } 
    } 

    #endregion 
} 
Problemi correlati