2014-05-20 4 views
6

Setup:SignalR Client nach Owin Neustart wieder angeschlossen, aber Meldung wird nicht veröffentlicht

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

ich wie folgt vor:

  1. Hit auf den Client eingeben, wird eine Meldung wieder auf dem Server und auf dem Client empfangen
  2. den Server Entsorgen Sie eine beliebige Taste in der Server-Konsole schlägt
  3. Starten Sie den Server durch eine beliebige Taste in der Server-Konsole
  4. Client verbunden ist
  5. Hit geben Sie auf dem Client schlägt, wird Nachricht an Server empfangen, aber nie erreicht der Kunde wieder

Ich erwarte, dass die Nachricht erneut auf dem Client empfangen wird. Ich vermute, dass es etwas mit dem Self-Hosting zu tun hat, da ich versucht habe, den Client gegen denselben Hub in einer Web-Anwendung laufen zu lassen, auf der IIS erfolgreich läuft.

Irgendwelche Ideen?

Update: Wenn der Serverkonsolenprozess abgebrochen und neu gestartet wird, kann er die Nachrichten erneut verbinden UND abrufen.

Server Code

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(); 
     } 
    } 
} 

Client-Code

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

Ich wünsche ich mehr helfen konnte, aber ich kopiert Ihren Server und Client-Code wörtlich in zwei Konsole App-Projekte. Nach der Installation der notwendigen NuGet-Pakete konnte ich die Server-App neu starten, den Client automatisch neu verbinden lassen und danach weiterhin Nachrichten senden und empfangen. – halter73

+0

Ich habe die Schritte aktualisiert, um genauer zu sein. Sie sollten die Serverkonsolen-App selbst, aber die SignalR-Server-App selbst neu starten. – Stian

Antwort

5

Das SignalR Team wies mich auf die Lösung: standardmäßig SignalR verwendet GlobalHost, die ein Singleton Resolver ist. Wenn es entsorgt wird, wird es niemals zurückkommen.

Wenn die Konfiguration für die Nabe zu schaffen, sollten Sie inn eine neue Abhängigkeitsauflöser passieren:

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

ich mit SignalR mehrere ähnliche Probleme hat (nicht exacly im gleichen Szenario).

Das Problem wurde normalerweise im Kommunikationsmodell request_from_server-> client-> response_to_server verursacht. Als ich versuchte, Invoke im Client-Code (um eine Antwort an den Server zu senden) direkt in der Empfangsprozedur aufzurufen, bekam ich seltsames Verhalten (unendliche Wartezeiten, seltsame Nebeneffekte usw.).

Lösung war Prozess in zwei Threads zu teilen. Eine für den Empfang von Nachrichten vom Server an lokale ConcurrentQueue.Der zweite Thread ruft Nachrichten aus der Warteschlange ab, verarbeitet sie und sendet Antworten an den Server (über Invoke). Jetzt funktioniert SignalR wie erwartet.

Dieses Problem wurde wahrscheinlich verursacht, indem versucht wurde, die Antwort zu senden, BEVOR die Empfangsprozedur beendet wurde. Dies geschieht nicht im üblichen Client-> Server-> Client-Kommunikationsmodell.

1

Stians Antwort ist großartig. Wenn Sie jedoch die in GlobalHost definierten statischen Methoden verwenden müssen, müssen Sie den Dependency-Resolver GlobalHost zuweisen.

Die folgenden Werke für mich:

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

I definiert die Nabe Kontext auf diese Weise:

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 
} 
Verwandte Themen