2009-03-12 10 views
20

Ich erstelle eine Silverlight 2-Benutzeroberfläche für ein Remote-Instrument. Es gibt zwei gleichzeitige Benutzer an verschiedenen Standorten, die mit dem Instrument interagieren (Bediener am Instrument und Fernwissenschaftler) und eine beliebige Anzahl von Beobachtern, die nicht mit ihm interagieren, nur zusehen. Wenn jedoch einer der beiden aktiven Benutzer etwas ändert, müssen diese Änderungen sofort in den Benutzeroberflächen aller Benutzer widergespiegelt werden, z. Verschieben oder Zoomen eines Bildes oder Annotieren oder Auswählen eines Bildteils, Hinzufügen von Elementen zu einer in einer Listbox angezeigten Sammlung. Innerhalb des Clients verwende ich beobachtbare Sammlungen, die leicht Änderungen widerspiegeln, die von diesem Benutzer vorgenommen wurden, aber es ist schwieriger, Änderungen von einem anderen Benutzer zu sehen. Ich kann für Änderungen von jedem Kunden abfragen, aber etwas wie Push-Benachrichtigungen wäre besser. Ich habe extensiv nach Beispielen gegoogelt, aber nichts gefunden, was ich wirklich brauche. Es gibt alle Arten von Sicherheitsproblemen, wenn Silverlight mit WCF-Diensten interagiert, was bedeutet, dass viele potentielle Beispiele einfach nicht funktionieren. Ich habe im Wesentlichen keine Zeit für dieses Projekt und brauche schnell Hilfe. Hat jemand einen Vorschlag für ein geeignetes einfaches Beispiel, das zeigt, wie man das macht? Ich bin ein erfahrener Entwickler, musste mir aber Silverlight und WCF-Dienste selbst beibringen und es gibt niemanden in meiner Gegend, der etwas darüber weiß. Selbst wenn ich eine Menge ASP.NET-Arbeit gemacht habe, bin ich kein Web-/Javascript-Guru. Vielen Dank.Silverlight und Push-Benachrichtigungen

Antwort

10

Push-Benachrichtigung wird in Silverlight 2 mit der neuen WCF PollingDuplexHttpBinding-Unterstützung unterstützt. Es sind zwei Assemblys mit dem Silverlight SDK (one for Silverlight app one for WCF server) installiert.

Ich habe eine few blog posts and a full sample application, die zeigen, wie 'Stock' Updates von einem Konsolenanwendungsserver, der einen WCF-Dienst an verbundene Clients hostet, "pushen". Es zeigt auch, wie jeder Kunde Notizen zu einem Stock hinzufügen kann und diese Notizen mit allen anderen verbundenen Clients synchronisiert (vom Server übertragen).

Die neueste Version der Probe (Teil 4) zeigt, wie geschoben Updates zwischen den beiden Silverlight und WPF Clients Endpunkte mit zwei Server synchronisieren, wie folgt:

using System; 
using System.ServiceModel; 
using System.ServiceModel.Description; 

namespace StockServer 
{ 
    public class StockServiceHost : ServiceHost 
    { 
     public StockServiceHost(object singletonInstance, params Uri[] baseAddresses) 
      : base(singletonInstance, baseAddresses) 
     { 
     } 

     public StockServiceHost(Type serviceType, params Uri[] baseAddresses) 
      : base(serviceType, baseAddresses) 
     { 
     } 

     protected override void InitializeRuntime() 
     { 
      this.AddServiceEndpoint(
       typeof(IPolicyProvider), 
       new WebHttpBinding(), 
       new Uri("http://localhost:10201/")).Behaviors.Add(new WebHttpBehavior()); 

      this.AddServiceEndpoint(
       typeof(IStockService), 
       new PollingDuplexHttpBinding(), 
       new Uri("http://localhost:10201/SilverlightStockService")); 

      this.AddServiceEndpoint(
       typeof(IStockService), 
       new WSDualHttpBinding(WSDualHttpSecurityMode.None), 
       new Uri("http://localhost:10201/WpfStockService")); 

      base.InitializeRuntime(); 
     } 
    } 
} 

WPF-Clients eine Verbindung mit dem WSDualHttpBinding Endpunkt und Silverlight-Clients Stellen Sie eine Verbindung mit dem PollingDuplexHttpBinding-Endpunkt desselben WCF-Diensts her. Die App zeigt außerdem, wie die Richtlinienanforderungen für den Silverlight-Clientzugriff gehandhabt werden.

Clients (Silverlight oder WPF) können in ihrer Benutzeroberfläche Notizen zu einem Stock hinzufügen und diese Notizen werden an den Server weitergeleitet, um an alle anderen Clients übertragen zu werden. Dies zeigt die Kommunikation in beide Richtungen und führt hoffentlich die gesamte notwendige Kommunikation für Ihre App durch.

Sie können einen Screenshot der demo application running here sehen.

+1

Führt PollingDuplexHttpBinding seinen "Push" nicht durch Abfragen aus, daher der Name? – gbjbaanb

+1

Es verwendet langanhaltende HTTP-Verbindungen im COMET-Stil, technisch gesehen ist es also ein Polling, aber da die Polling-Schleife so lang ist (wenn es keine Daten gibt), ist es eher analog zur Registrierung eines Callbacks beim Server. – luke

6

Nicht das ist Flex in Fan-Boy-Mode, aber eigentlich ist das die Art von Architektur, die wir in all unseren Flex-basierten Anwendungen routinemäßig einbauen. Hier ist, was wir auf Flex tun - kein Zweifel könnte es passend zu Silverlight übersetzt werden:

Wir nehmen drei Zutaten und integrieren sie zusammen, um diese Fähigkeit zu erreichen:

  1. Comet Muster (eine HTTP-kompatible Art und Weise zu tun Server-Push-Benachrichtigungen - suchen auf Wikipedia für weitere Informationen)
  2. JMS-Messaging-Themen (Publish/Subscriber-Queues)
  3. Die Adobe BlazeDS Servlet

Das letzte Element implementiert das Comet-Muster, unterstützt AMF-Objekt-Marshalling (Adobes binäres Serialisierungsformat für ActionScript3-Objekte) und überbrückt eine JMS-Warteschlange oder ein JMS-Thema. Bei der Überleitung zu einem Thema können mehrere Flex-Clients, die in einem Browser ausgeführt werden, als Abonnenten eines JMS-Themas weitergeleitet werden. Wenn also ein Client eine Nachricht veröffentlicht (oder der serverseitige Code in das Thema veröffentlicht wird), wird allen Kunden die Nachricht über BlazeDS und die Comet Pattern-Implementierung zugestellt.

Effektiv müssen Sie eine Komponente finden oder schreiben, die das leistet, was BlazeDS tut. Möglicherweise müssen Sie auch Clientcode implementieren, der mit dem Comet-Muster dieser serverseitigen Komponente interagiert.

Unterstützt WCF das Kometenmuster und das bidirektionale Messaging? Vor allem, wenn HTTP und Port 80 oder Port 443 für SSL entspricht. Sieht so aus, als hättest du schon darüber nachgedacht und nichts für bidirektionales Messaging gefunden. Also müssen Sie vielleicht die Ärmel hochkrempeln und etwas codieren.

Einige Dinge über das Tun Server Push-to-Web-App zu beachten:

BlazeDS unterstützt zwei primäre Arten der Durchführung des Comet-Musters (es gibt tatsächlich eine dritte Wahl Option, aber es werden zu ignorieren):

  1. lang~~POS=TRUNC Polling
  2. HTTP-Streaming

Die lang Polling, die Sie finden sollte universell erträglich zu den meisten Web-Browsern zu sein. Sie können also zunächst nur das unterstützen. Oder Sie könnten die Zeit dafür aufwenden, dass Ihr Client-Code zunächst HTTP-Streaming versucht und bei Bedarf auf Long-Polling umschaltet.

In Bezug auf einen Nachrichtenbroker, der Publish/Subscribe-Capability bereitstellen kann, sollten Sie ActiveMQ JMS verwenden. Es ist Open Source und kostenlos mit aktiver Community-Unterstützung (Sie können auch Unterstützung kaufen). Außerdem können Sie NMS zur Integration als .NET-Client verwenden.

Es ist eigentlich wichtig, einen Nachrichtenbroker zu haben, der sich in der mittleren Schicht befindet, da hier Nachrichten sicher platziert werden können. Wenn Ihre Clients lange Abfragen durchführen, möchten Sie nicht, dass sie während eines Intervalls eine neue Nachricht verpassen, wenn sie nicht wirklich verbunden sind.

Eine weitere Sache, die bei Szenarien mit hohem Datenaufkommen (Hunderte oder Tausende von Clients, wie eine Website im Internet) zu berücksichtigen ist, ist ein skalierbarer Ansatz für das Comet-Muster.

In der Flex/Java-Welt wurde das BlazeDS-Servlet (Open Source) für das asynchrone Modell modifiziert. In Java kann ein Socket-Listener erstellt werden, um NIO-Kanäle und Java Concurrency Executor-Thread-Pools zu verwenden. Der Tomcat-Webserver verfügt über einen NIO-Listener und Unterstützung für asynchrone Servlet 3.0-Ereignisse. Vor allem BlazeDS wurde modifiziert, um mit dem Jetty-Webserver zu arbeiten. Unter dem Strich bedeutet die Skalierbarkeit dieses asynchronen Ansatzes, dass ein einzelner physischer Webserver so erweitert werden kann, dass er bis zu 20.000 gleichzeitige Comet-Clientverbindungen unterstützt.

Es ist eine Weile her, seit ich ernsthafte .NET-Programmierung gemacht habe, aber die io-Fähigkeiten waren wie Java 1.1, außer mit einer asynchronen Ergebnisbehandlungsfunktion. Dies ist jedoch nicht das Gleiche wie das Erstellen asynchroner Socket-Listener über Java-NIO-Kanäle. Eine NIO-Channel-Implementierung kann Hunderte bis Tausende von Socket-Verbindungen mit einem relativ kleinen Thread-Pool unterstützen. Aber C# und .NET haben zwei oder drei signifikante Umdrehungen durchgemacht - vielleicht wurden neue io-Fähigkeiten hinzugefügt, die mit NIO-Kanälen vergleichbar sind.

0

Die PollingDuplexHttpBinding ist wahrscheinlich die eleganteste Art und Weise, dies zu tun.

Eine möglicherweise weniger komplizierte Alternative ist die Verwendung eines TCP-Sockets von Ihrem Silverlight-Client. Wenn an einem der Silverlight-Clients ein Update gesendet werden muss, können Sie ihm eine TCP-Nachricht senden, die den Namen des WCF-Dienstes enthält, den er anrufen muss, oder eine andere leichtgewichtige Information.

Ich verwende diesen Ansatz für eine Anwendung und es funktioniert gut.

1

Meine Organisation fand die Silverlight 2.0/WCF-Push-Implementierung etwas "nicht bereit für die Prime Time", zumindest für das, wofür wir es geplant hatten.

Wir gingen mit XMPP/Jabber, denn es ist ein besser gestaltetes Biest, und Sie können es ziemlich einfach in Silverlight implementieren, indem Sie nur einige Ressourcen aus dem Internet bekommen.

Ich glaube, dass Silverlight 3.0 eine neuere/besser geformte Push-Implementierung implementieren wird, aus dem, was ich aus öffentlich verfügbaren Informationen erkennen kann.

2

Alternativ

, wenn Sie eine native Silverlight-API ohne Proxies, Brücken oder webservers wollen beteiligt Sie Nirvana von My-Channels als Messaging-Middleware nutzen könnten. Sieh dir Nirvana von my-Channels und ihrer Vorstellungsseite an. (Sorry, ich bin ein neuer Benutzer und kippt Links einreichen):

Alex

+0

Wir verwenden Nirvana mit Silverlight, es ist ziemlich nett. :) – RhysC

2

EDIT: es ist eigentlich gut funktioniert. Ich hatte schlecht von den „verborgenen Variablen“ in einem Verschluss gebissen :(

ich die PollingDuplex für SL2 verwendet und ich denke, dass es noch für die Produktion nicht bereit ist.

Mein Hauptproblem ist die Tatsache, dass es doesn‘ t diskriminiere auf den Clients auf dem gleichen Rechner.Wenn ich 2 Clients betreibe, dann wird einer von ihnen den Server nicht mehr abfragen können und wird von Timeout sterben.Es gibt eine SessionId, die für die 2 Clients unterschiedlich ist, aber sie wird einfach ignoriert auf der Client-Seite

Ebenso, wenn ich einen Klienten töte und dann einen neuen danach gründe, dann erhält der neue Klient die Stoßaktualisierungen vom vorherigen Klienten für eine Weile.

Hat jemand die gleichen Probleme oder sind sie in SL3 behoben?

Eigentlich habe ich noch ein paar Demo-Codes ausgeführt und festgestellt, dass Sie aus irgendeinem Grund den InstanceContextMode und den InstanceMode angeben müssen, damit der Dienst sitzungsbasiert und kein Singleton ist (soweit ich das beurteilen kann). Es gibt klare Leistungsprobleme in dem einfachen Demo-Code, den ich gezogen habe.

Es ist ziemlich bedauerlich, dass dieses Verhalten nicht dokumentiert wurde.

3

Ich wollte nur klarstellen, dass das PollingDuplexHttpBinding keine "echten" Push-Benachrichtigungen implementiert, wie der Name (Polling) verrät. Vom msdn documentation:

Wenn mit dieser konfiguriert Bindung, die Silverlight-Client in regelmäßigen Abständen Umfragen der Dienst auf der Netzwerkschicht, und prüft, ob neue Nachrichten, die der Dienst will sich auf der Callback-Kanal senden. Der Dienst stellt alle Nachrichten, die auf dem Client-Rückrufkanal gesendet werden, in eine Warteschlange und liefert sie an den Client, wenn der Client den Dienst abfragt.

Allerdings ist es effizienter, als die traditionelle Art der Abfrage eines Web-Service, da nach jeder Umfrage, der Server den Kanal für eine bestimmte Zeit offen halten (etwa 1 Minute), und wenn eine Nachricht, dass ankommt Zeit wird es direkt die Nachricht an den Client "pushen". Der Client muss seine Verbindung wiederholt erneuern, sozusagen den Dienst abfragen.

Wenn Sie echte Push-Benachrichtigungen mit Silverlight implementieren wollen, glaube ich, dass Sie mit Sockets arbeiten müssen, und ich empfehle, einige von Dan Wahlins Blogposts zu diesem Thema zu lesen.