Tutorial: Erstellen einer Hochfrequenz-Echtzeit-App mit SignalR 2
In diesem Tutorial wird gezeigt, wie Sie eine Webanwendung erstellen, die ASP.NET SignalR 2 verwendet, um hochfrequente Messagingfunktionen bereitzustellen. In diesem Fall bedeutet "Hochfrequenzmessaging", dass der Server Updates mit einer festen Rate sendet. Sie senden bis zu 10 Nachrichten pro Sekunde.
Die von Ihnen erstellte Anwendung zeigt eine Form an, die Benutzer ziehen können. Der Server aktualisiert die Position des Shapes in allen verbundenen Browsern so, dass sie mit zeitgesteuerten Updates der Position des gezogenen Shapes entspricht.
Die in diesem Tutorial vorgestellten Konzepte enthalten Anwendungen für Echtzeitspiele und andere Simulationsanwendungen.
In diesem Tutorial:
- Einrichten des Projekts
- Erstellen der Basisanwendung
- Zuordnen zum Hub beim Starten der App
- Hinzufügen des Clients
- Ausführen der App
- Hinzufügen der Clientschleife
- Hinzufügen der Serverschleife
- Hinzufügen einer reibungslosen Animation
Warnung
Diese Dokumentation gilt nicht für die neueste Version von SignalR. Sehen Sie sich ASP.NET Core SignalR an.
Voraussetzungen
- Visual Studio 2017 mit der Workload ASP.NET und Webentwicklung
Einrichten des Projekts
In diesem Abschnitt erstellen Sie das Projekt in Visual Studio 2017.
In diesem Abschnitt wird gezeigt, wie Sie visual Studio 2017 verwenden, um eine leere ASP.NET-Webanwendung zu erstellen und die SignalR- und jQuery.UI-Bibliotheken hinzuzufügen.
Erstellen Sie in Visual Studio eine ASP.NET Webanwendung.
Lassen Sie im Fenster Neue ASP.NET Webanwendung – MoveShapeDemodie Option Leer ausgewählt, und wählen Sie OK aus.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieNeues Elementhinzufügen> aus.
Wählen Sie unter Neues Element hinzufügen – MoveShapeDemodie Option Installiertes>Visual C#>Web>SignalR und dann SignalR Hub-Klasse (v2) aus.
Nennen Sie die Klasse MoveShapeHub , und fügen Sie sie dem Projekt hinzu.
In diesem Schritt wird die MoveShapeHub.cs-Klassendatei erstellt. Gleichzeitig werden dem Projekt skriptdateien und Assemblyverweise hinzugefügt, die SignalR unterstützen.
Klicken Sie auf Extras>NuGet-Paket-Manager>Paket-Manager-Konsole.
Führen Sie in der Paket-Manager-Konsole den folgenden Befehl aus:
Install-Package jQuery.UI.Combined
Mit dem Befehl wird die jQuery-UI-Bibliothek installiert. Sie verwenden es, um die Form zu animieren.
Erweitern Sie in Projektmappen-Explorer den Knoten Skripts.
Skriptbibliotheken für jQuery, jQueryUI und SignalR sind im Projekt sichtbar.
Erstellen der Basisanwendung
In diesem Abschnitt erstellen Sie eine Browseranwendung. Die App sendet den Speicherort des Shapes während jedes Mausbewegungsereignisses an den Server. Der Server sendet diese Informationen in Echtzeit an alle anderen verbundenen Clients. Weitere Informationen zu dieser Anwendung finden Sie in späteren Abschnitten.
Öffnen Sie die Datei MoveShapeHub.cs .
Ersetzen Sie den Code in der Datei MoveShapeHub.cs durch diesen Code:
using Microsoft.AspNet.SignalR; using Newtonsoft.Json; namespace MoveShapeDemo { public class MoveShapeHub : Hub { public void UpdateModel(ShapeModel clientModel) { clientModel.LastUpdatedBy = Context.ConnectionId; // Update the shape model within our broadcaster Clients.AllExcept(clientModel.LastUpdatedBy).updateShape(clientModel); } } public class ShapeModel { // We declare Left and Top as lowercase with // JsonProperty to sync the client and server models [JsonProperty("left")] public double Left { get; set; } [JsonProperty("top")] public double Top { get; set; } // We don't want the client to get the "LastUpdatedBy" property [JsonIgnore] public string LastUpdatedBy { get; set; } } }
Speichern Sie die Datei .
Die MoveShapeHub
-Klasse ist eine Implementierung eines SignalR-Hubs. Wie im Tutorial Erste Schritte mit SignalR verfügt der Hub über eine Methode, die die Clients direkt aufrufen. In diesem Fall sendet der Client ein Objekt mit den neuen X- und Y-Koordinaten des Shapes an den Server. Diese Koordinaten werden an alle anderen verbundenen Clients gesendet. SignalR serialisiert dieses Objekt automatisch mithilfe von JSON.
Die App sendet das ShapeModel
Objekt an den Client. Es verfügt über Elemente, um die Position des Shapes zu speichern. Die Version des Objekts auf dem Server verfügt auch über einen Member, um nachzuverfolgen, welche Clientdaten gespeichert werden. Dieses Objekt verhindert, dass der Server die Daten eines Clients zurück an sich selbst sendet. Dieses Element verwendet das JsonIgnore
-Attribut, um zu hindern, dass die Anwendung die Daten serialisiert und an den Client zurück sendet.
Zuordnen zum Hub beim Starten der App
Als Nächstes richten Sie die Zuordnung zum Hub ein, wenn die Anwendung gestartet wird. In SignalR 2 erstellt das Hinzufügen einer OWIN-Startklasse die Zuordnung.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieNeues Elementhinzufügen> aus.
Wählen Sie unter Neues Element hinzufügen – MoveShapeDemodie Option Installiertes>Visual C#>Web und dann OWIN-Startklasse aus.
Nennen Sie die Klasse Startup , und wählen Sie OK aus.
Ersetzen Sie den Standardcode in der Datei Startup.cs durch diesen Code:
using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(MoveShapeDemo.Startup))] namespace MoveShapeDemo { public class Startup { public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here app.MapSignalR(); } } }
Die OWIN-Startklasse ruft auf MapSignalR
, wenn die App die Configuration
-Methode ausführt. Die App fügt die -Klasse dem Startprozess von OWIN mithilfe des OwinStartup
Assembly-Attributs hinzu.
Hinzufügen des Clients
Fügen Sie die HTML-Seite für den Client hinzu.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen SieHTML-Seitehinzufügen> aus.
Nennen Sie die Seite Standard, und wählen Sie OK aus.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf Default.html, und wählen Sie Als Startseite festlegen aus.
Ersetzen Sie den Standardcode in der Default.html-Datei durch diesen Code:
<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/jquery-ui-1.10.4.min.js"></script> <script src="Scripts/jquery.signalR-2.1.0.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), shapeModel = { left: 0, top: 0 }; moveShapeHub.client.updateShape = function (model) { shapeModel = model; $shape.css({ left: model.left, top: model.top }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moveShapeHub.server.updateModel(shapeModel); } }); }); }); </script> <div id="shape" /> </body> </html>
Erweitern Sie in Projektmappen-ExplorerSkripts.
Skriptbibliotheken für jQuery und SignalR sind im Projekt sichtbar.
Wichtig
Der Paket-Manager installiert eine höhere Version der SignalR-Skripts.
Aktualisieren Sie die Skriptverweise im Codeblock so, dass sie den Versionen der Skriptdateien im Projekt entsprechen.
Mit diesem HTML- und JavaScript-Code wird ein Rot div
namens shape
erstellt. Es aktiviert das Ziehverhalten des Shapes mithilfe der jQuery-Bibliothek und verwendet das drag
-Ereignis, um die Position des Shapes an den Server zu senden.
Ausführen der App
Sie können die App ausführen, damit sie funktioniert. Wenn Sie das Shape um ein Browserfenster ziehen, wird das Shape auch in den anderen Browsern verschoben.
Aktivieren Sie auf der Symbolleiste skriptdebuggen , und wählen Sie dann die Schaltfläche Wiedergabe aus, um die Anwendung im Debugmodus auszuführen.
Ein Browserfenster mit der roten Form in der oberen rechten Ecke wird geöffnet.
Kopieren Sie die URL der Seite.
Öffnen Sie einen anderen Browser, und fügen Sie die URL in die Adressleiste ein.
Ziehen Sie die Form in eines der Browserfenster. Die Form im anderen Browserfenster folgt.
Obwohl die Anwendungsfunktionen diese Methode verwenden, ist dies kein empfohlenes Programmiermodell. Es gibt keine Obergrenze für die Anzahl der gesendeten Nachrichten. Dies führt dazu, dass die Clients und der Server mit Nachrichten und Leistungseinbußen überlastet werden. Außerdem zeigt die App eine nicht zusammenhängende Animation auf dem Client an. Diese ruckartige Animation erfolgt, weil sich die Form sofort von jeder Methode bewegt. Es ist besser, wenn sich die Form reibungslos an jede neue Position bewegt. Als Nächstes erfahren Sie, wie Sie diese Probleme beheben.
Hinzufügen der Clientschleife
Das Senden der Position des Shapes bei jedem Mausbewegungsereignis führt zu einer unnötigen Menge an Netzwerkdatenverkehr. Die App muss die Nachrichten vom Client drosseln.
Verwenden Sie die Javascript-Funktion setInterval
, um eine Schleife einzurichten, die neue Positionsinformationen mit einer festen Rate an den Server sendet. Diese Schleife ist eine grundlegende Darstellung einer "Spielschleife". Es ist eine wiederholt genannte Funktion, die die gesamte Funktionalität eines Spiels antreibt.
Ersetzen Sie den Clientcode in der Default.html-Datei durch diesen Code:
<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/jquery-ui-1.10.4.min.js"></script> <script src="Scripts/jquery.signalR-2.1.0.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // Determine how often to send messages in // time to abide by the messageFrequency updateRate = 1000 / messageFrequency, shapeModel = { left: 0, top: 0 }, moved = false; moveShapeHub.client.updateShape = function (model) { shapeModel = model; $shape.css({ left: model.left, top: model.top }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moved = true; } }); // Start the client side server update interval setInterval(updateServerModel, updateRate); }); function updateServerModel() { // Only update server if we have a new movement if (moved) { moveShapeHub.server.updateModel(shapeModel); moved = false; } } }); </script> <div id="shape" /> </body> </html>
Wichtig
Sie müssen die Skriptverweise erneut ersetzen. Sie müssen mit den Versionen der Skripts im Projekt übereinstimmen.
Mit diesem neuen Code wird die
updateServerModel
Funktion hinzugefügt. Es wird mit einer festen Häufigkeit aufgerufen. Die Funktion sendet die Positionsdaten immer dann an den Server, wenn dasmoved
Flag anzeigt, dass neue Positionsdaten gesendet werden.Wählen Sie die Wiedergabeschaltfläche aus, um die Anwendung zu starten.
Kopieren Sie die URL der Seite.
Öffnen Sie einen anderen Browser, und fügen Sie die URL in die Adressleiste ein.
Ziehen Sie die Form in eines der Browserfenster. Die Form im anderen Browserfenster folgt.
Da die App die Anzahl der Nachrichten, die an den Server gesendet werden, drosselt, wird die Animation zunächst nicht so reibungslos angezeigt.
Hinzufügen der Serverschleife
In der aktuellen Anwendung werden nachrichten, die vom Server an den Client gesendet werden, so oft wie sie empfangen werden. Dieser Netzwerkdatenverkehr stellt ein ähnliches Problem wie auf dem Client dar.
Die App kann Nachrichten häufiger senden, als sie benötigt werden. Die Verbindung kann dadurch überschwemmt werden. In diesem Abschnitt wird beschrieben, wie Sie den Server aktualisieren, um einen Timer hinzuzufügen, der die Rate der ausgehenden Nachrichten drosselt.
Ersetzen Sie den Inhalt von
MoveShapeHub.cs
durch den folgenden Code:using System; using System.Threading; using Microsoft.AspNet.SignalR; using Newtonsoft.Json; namespace MoveShapeDemo { public class Broadcaster { private readonly static Lazy<Broadcaster> _instance = new Lazy<Broadcaster>(() => new Broadcaster()); // We're going to broadcast to all clients a maximum of 25 times per second private readonly TimeSpan BroadcastInterval = TimeSpan.FromMilliseconds(40); private readonly IHubContext _hubContext; private Timer _broadcastLoop; private ShapeModel _model; private bool _modelUpdated; public Broadcaster() { // Save our hub context so we can easily use it // to send to its connected clients _hubContext = GlobalHost.ConnectionManager.GetHubContext<MoveShapeHub>(); _model = new ShapeModel(); _modelUpdated = false; // Start the broadcast loop _broadcastLoop = new Timer( BroadcastShape, null, BroadcastInterval, BroadcastInterval); } public void BroadcastShape(object state) { // No need to send anything if our model hasn't changed if (_modelUpdated) { // This is how we can access the Clients property // in a static hub method or outside of the hub entirely _hubContext.Clients.AllExcept(_model.LastUpdatedBy).updateShape(_model); _modelUpdated = false; } } public void UpdateShape(ShapeModel clientModel) { _model = clientModel; _modelUpdated = true; } public static Broadcaster Instance { get { return _instance.Value; } } } public class MoveShapeHub : Hub { // Is set via the constructor on each creation private Broadcaster _broadcaster; public MoveShapeHub() : this(Broadcaster.Instance) { } public MoveShapeHub(Broadcaster broadcaster) { _broadcaster = broadcaster; } public void UpdateModel(ShapeModel clientModel) { clientModel.LastUpdatedBy = Context.ConnectionId; // Update the shape model within our broadcaster _broadcaster.UpdateShape(clientModel); } } public class ShapeModel { // We declare Left and Top as lowercase with // JsonProperty to sync the client and server models [JsonProperty("left")] public double Left { get; set; } [JsonProperty("top")] public double Top { get; set; } // We don't want the client to get the "LastUpdatedBy" property [JsonIgnore] public string LastUpdatedBy { get; set; } } }
Wählen Sie die Wiedergabeschaltfläche aus, um die Anwendung zu starten.
Kopieren Sie die URL der Seite.
Öffnen Sie einen anderen Browser, und fügen Sie die URL in die Adressleiste ein.
Ziehen Sie die Form in eines der Browserfenster.
Dieser Code erweitert den Client, um die Broadcaster
-Klasse hinzuzufügen. Die neue Klasse drosselt die ausgehenden Nachrichten mithilfe der Timer
-Klasse aus dem .NET Framework.
Es ist gut zu erfahren, dass der Hub selbst transitorisch ist. Es wird jedes Mal erstellt, wenn es benötigt wird. Die App erstellt also als Broadcaster
Singleton. Es verwendet die verzögerte Initialisierung, um die Erstellung der Broadcaster
Erstellung zu verzögern, bis sie benötigt wird. Dadurch wird sichergestellt, dass die App den ersten Hub instance vollständig erstellt, bevor der Timer gestartet wird.
Der Aufruf der Clientfunktion UpdateShape
wird dann aus der -Methode des Hubs UpdateModel
verschoben. Sie wird nicht mehr sofort aufgerufen, wenn die App eingehende Nachrichten empfängt. Stattdessen sendet die App die Nachrichten mit einer Rate von 25 Aufrufen pro Sekunde an die Clients. Der Prozess wird vom _broadcastLoop
Timer innerhalb der Broadcaster
-Klasse verwaltet.
Schließlich muss die -Klasse einen Verweis auf den derzeit ausgeführten _hubContext
Hub abrufen, anstatt die Broadcaster
Clientmethode direkt vom Hub aus aufzurufen. Es ruft den Verweis mit dem GlobalHost
ab.
Hinzufügen einer reibungslosen Animation
Die Anwendung ist fast fertig, aber wir könnten eine weitere Verbesserung vornehmen. Die App verschiebt die Form auf dem Client als Reaktion auf Servernachrichten. Verwenden Sie die Funktion der JQuery-UI-Bibliothek animate
, anstatt die Position des Shapes auf den vom Server angegebenen neuen Speicherort festzulegen. Es kann das Shape reibungslos zwischen seiner aktuellen und neuen Position verschieben.
Aktualisieren Sie die Methode des
updateShape
Clients in der Default.html-Datei so, dass sie wie der hervorgehobene Code aussieht:<!DOCTYPE html> <html> <head> <title>SignalR MoveShape Demo</title> <style> #shape { width: 100px; height: 100px; background-color: #FF0000; } </style> </head> <body> <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/jquery-ui-1.10.4.min.js"></script> <script src="Scripts/jquery.signalR-2.1.0.js"></script> <script src="/signalr/hubs"></script> <script> $(function () { var moveShapeHub = $.connection.moveShapeHub, $shape = $("#shape"), // Send a maximum of 10 messages per second // (mouse movements trigger a lot of messages) messageFrequency = 10, // Determine how often to send messages in // time to abide by the messageFrequency updateRate = 1000 / messageFrequency, shapeModel = { left: 0, top: 0 }, moved = false; moveShapeHub.client.updateShape = function (model) { shapeModel = model; // Gradually move the shape towards the new location (interpolate) // The updateRate is used as the duration because by the time // we get to the next location we want to be at the "last" location // We also clear the animation queue so that we start a new // animation and don't lag behind. $shape.animate(shapeModel, { duration: updateRate, queue: false }); }; $.connection.hub.start().done(function () { $shape.draggable({ drag: function () { shapeModel = $shape.offset(); moved = true; } }); // Start the client side server update interval setInterval(updateServerModel, updateRate); }); function updateServerModel() { // Only update server if we have a new movement if (moved) { moveShapeHub.server.updateModel(shapeModel); moved = false; } } }); </script> <div id="shape" /> </body> </html>
Wählen Sie die Wiedergabeschaltfläche aus, um die Anwendung zu starten.
Kopieren Sie die URL der Seite.
Öffnen Sie einen anderen Browser, und fügen Sie die URL in die Adressleiste ein.
Ziehen Sie die Form in eines der Browserfenster.
Die Bewegung der Form im anderen Fenster erscheint weniger ruckartig. Die App interpoliert ihre Bewegung im Laufe der Zeit, anstatt einmal pro eingehender Nachricht festgelegt zu werden.
Dieser Code verschiebt die Form von der alten Position in die neue Position. Der Server gibt die Position der Form im Verlauf des Animationsintervalls an. In diesem Fall sind das 100 Millisekunden. Die App löscht alle vorherigen Animationen, die auf dem Shape ausgeführt werden, bevor die neue Animation gestartet wird.
Abrufen des Codes
Abgeschlossenes Projekt herunterladen
Zusätzliche Ressourcen
Das Kommunikationsparadigma, über das Sie gerade gelernt haben, ist nützlich für die Entwicklung von Online-Spielen und anderen Simulationen, wie das mit SignalR erstellte ShootR-Spiel.
Weitere Informationen zu SignalR finden Sie in den folgenden Ressourcen:
Nächste Schritte
In diesem Tutorial:
- Einrichten des Projekts
- Erstellen der Basisanwendung
- Beim Starten der App dem Hub zugeordnet
- Client hinzugefügt
- App ausgeführt
- Clientschleife hinzugefügt
- Serverschleife hinzugefügt
- Glatte Animation hinzugefügt
Fahren Sie mit dem nächsten Artikel fort, um zu erfahren, wie Sie eine Webanwendung erstellen, die ASP.NET SignalR2 verwendet, um Serverübertragungsfunktionen bereitzustellen.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für