Dieser Artikel erschien zuerst in Ausgabe 217 of .net magazine - das weltweit meistverkaufte Magazin für Webdesigner und Entwickler.
WebSockets sind Teil der HTML5-Spezifikation, und die einfachste Art, sie zu betrachten, besteht darin, dass sie einen Standard für die Erstellung langjähriger bidirektionaler Verbindungen zwischen einem Browser und einem Server setzen. Wenn diese Verbindung besteht, können Browser Nachrichten an den Server zurücksenden (wie z. B. schnelleres Ajax), und, was noch wichtiger ist, der Server kann neue Informationen an verbundene Clients senden, sobald diese verfügbar sind. WebSockets ermöglichen eine Kommunikation mit extrem geringer Latenz bei geringem Overhead.
Es gibt seit vielen Jahren Techniken, um Daten an verbundene Clients zu senden, und diese wurden unter dem Begriff Comet zusammengefasst (siehe en.wikipedia.org/wiki/Comet_(programming) für Details). WebSockets bieten jedoch eine weitaus einfachere und standardisierte Möglichkeit, dies zu tun, und werden wahrscheinlich die Art und Weise revolutionieren, wie Benutzer Echtzeitschnittstellen erstellen. Derzeit sind WebSockets mit mehreren modernen Browsern kompatibel, und für diejenigen, die noch nicht an Bord sind, stehen Flash-Fallback-Optionen zur Verfügung.
Warum sie benutzen? Mit WebSockets können Sie Benutzererlebnisse in Echtzeit viel einfacher erstellen. Die Menschen haben sich bereits an ein Gefühl der Unmittelbarkeit in den Anwendungen gewöhnt, die sie regelmäßig verwenden, und möchten sich mit anderen Menschen verbunden fühlen, die einen Dienst nutzen. Der Aufstieg des Facebook-Chats, der Multiplayer-Online-Spiele, der Echtzeit-Updates von Twitter und der gemeinsamen Bearbeitung über Google Text & Tabellen haben den Weg für die Anwendungen der nächsten Jahre geebnet. Diese Art von Benutzererfahrungen wird immer beliebter, und WebSockets wird die Technologie dahinter sein. Es wird immer wichtiger zu wissen, wie man diese Art von Schnittstellen erstellt.
Wie nutzen wir diese großartige neue Technologie? Im Gegensatz zu einigen anderen Teilen der HTML5-Spezifikation benötigen WebSockets sowohl eine Client- als auch eine Serverkomponente. Sie sind daher nicht so einfach in Betrieb zu nehmen wie bei Dingen wie Video, Leinwand, Geolokalisierung oder Formularsteuerelementen. Lassen Sie sich jedoch nicht abschrecken, da es viele Optionen gibt, mit denen Sie beginnen können.
Die erste verfügbare Methode ist die Installation und Wartung Ihres eigenen Socket-Servers. Es gibt Open Source Projekte wie E / A-Buchse , die ziemlich einfach zu beginnen sind. Es ist jedoch nicht immer einfach, diese Art von Socket-Servern in einer durchschnittlichen Hosting-Umgebung zu installieren, da die Hosting-Sicherheitsbeschränkungen auferlegt und die Ressourcenzuweisungen für die langjährigen Verbindungen, die WebSockets benötigen, reduziert wurden.
Eine weitere Option ist die Verwendung eines gehosteten Dienstes, der in Ihre vorhandene Website-Infrastruktur integriert ist. Das bietet meine Firma Pusher.
Für die Tutorials verwende ich unseren Service, da die WebSocket-API ein bisschen 'Bare Bones' ist und eine Abstraktionsschicht die Kommunikation zwischen Client und Server verständlicher machen kann.
Die Abstraktionsschichten können auch gängige Szenarien wie das Behandeln von Verbindungen und das erneute Verbinden von Verbindungen verwalten und umfassendere Features und Funktionen hinzufügen. Beispielsweise kann eine Bibliothek, die WebSockets umschließt, als ähnlich angesehen werden, wie jQuery den Zugriff auf grundlegende DOM-Manipulationen umschließt. denken document.getElementById ('myDiv') vs. jQuery ('# myDiv') .
Wenn wir sagen, dass WebSockets Teil der HTML5-Spezifikation sind, ist nicht unbedingt klar, was dies bedeutet. In der Praxis bedeutet dies keine Änderung des HTML-Codes der Seite, sondern die Funktionalität wird über einige neue JavaScript-APIs verfügbar gemacht. Das erste, was neu ist, ist ein WebSocket-Objekt, das mit der URL initialisiert wird, zu der es eine Verbindung herstellen muss:
var ws = new WebSocket('ws://example.com');
Dieses WebSocket-Objekt verfügt über mehrere Ereignisse, mit denen Sie sich in den Rest Ihres Codes einbinden können. Die Hauptereignisse treten auf, wenn eine Verbindung geöffnet wird, wenn sie geschlossen wird und wenn neue Nachrichten eintreffen.
socket.onopen = function(evt) { alert('Connection established') } socket.onclose = function(evt){ alert('Connection closed') } socket.onmessage = function(evt){ alert('I got data: ' + evt.data) }
Sie können auch Daten über die Verbindung senden:
socket.send( 'Have some data' );
Anhand des begrenzten Codes oben können Sie hoffentlich sehen, wie Twitter beispielsweise eine WebSocket-Verbindung herstellen kann, die bei ihrem Auftreten neue Tweets empfängt, damit diese auf der Seite angezeigt werden.
Um eine detailliertere Verwendung zu demonstrieren, habe ich ein Beispiel für eine Echtzeitumfrage genommen. Wenn dies eine vollständige Anwendung wäre, würde ich wahrscheinlich einige Dinge anders machen, aber ich kann zeigen, wie nützlich WebSockets sind.
In diesem Beispiel stellt unsere Anwendung die einfache Frage 'Was ist die beste Sprache?' Und bietet Schaltflächen, mit denen der Benutzer seine Wahl treffen kann. Über den Schaltflächen wird ein Diagramm angezeigt, das die Beliebtheit der verschiedenen Antworten verfolgt. Was dies interessanter macht, ist, dass Sie sehen können, wie sich die Ergebnisse in Echtzeit ändern, wenn Personen in anderen Browsern abstimmen.
Apple MacBook Pro umfasst 15 Zoll
Ich werde Ruby auf dem Server verwenden und versuchen, die Dinge ziemlich einfach zu halten, damit wir uns auf die WebSocket-Interaktion konzentrieren können. Ich werde Pusher auch für den WebSocket-Server verwenden, da es die Fallback-Unterstützung für ältere Browser hinzufügt. Den Quellcode finden Sie unter Github . Informationen zum Erstellen der Basisanwendung finden Sie im Abschnitt Erste Schritte. Wenn Sie lieber Echtzeitfunktionen hinzufügen möchten, Laden Sie die Basisanwendung herunter .
Zuerst müssen wir unsere grundlegende Survey Rails-Anwendung erstellen. Wir brauchen eine Datenbank, a SurveyEntry Modell, a Umfrageeinträge Controller und eine Ansicht zur Anzeige der Ergebnisse. In Ruby on Rails ist dies ganz einfach. Öffnen Sie eine Eingabeaufforderung oder ein Terminalfenster und geben Sie die folgenden Befehle ein:
Schienen neue realtime_survey - Erstellen Sie die neue Anwendung
cd realtime_survey - Navigieren Sie in das neue Anwendungsverzeichnis
Rechen db: erstellen - Erstellen Sie die Datenbank
Schienen erzeugen das Modell SurveyEntry. Auswahl: Zeichenfolge - Erstellen Sie die SurveyEntry Modell-
Schienen erzeugen Controller SurveyEntries Index erstellen - Erstellen Sie den SurveyEntries-Controller mit aufgerufenen Aktionen Index und erstellen
Rechen db: migrieren - Erstellen Sie die Umfrageeinträge Tabelle in der Datenbank für das SurveyEntry-Modell
Ein index.html.erb Datei sollte innerhalb der erstellt worden sein / app / views / umfrageeinträge Mappe. Dies ist die Ansicht für die Indexaktion des Umfrageeinträge Regler. Falls vorhanden, löschen Sie die index.html Datei in der gefunden App / Öffentlichkeit Verzeichnis und aktualisieren Sie die /config/routes.rb so dass die Indexaktion innerhalb der SurveyController wird standardmäßig aufgerufen.
RealtimeSurvey::Application.routes.draw doroot :to => 'survey_entries#index' resources :survey_entries end
Wenn Sie die ausführen Rails Server Befehl von der realtime_survey Verzeichnis und gehen Sie zu http: // localhost: 3000 Sie sehen den Inhalt des index.html.erb Aussicht. Fügen wir auch Code hinzu, der die Anzahl der Stimmen pro Sprache aus der Datenbank abruft, indem wir der Methode eine Methode hinzufügen SurveyEntry Modell ( query_entry.rb ). Wir werden die Programmiersprachenoptionen auch im Modell definieren.
class SurveyEntry :choice }) FORM_OPTIONS.map do |o| end end end
Dann sollten wir diesen Code von unserem Controller aus aufrufen und die Umfrageeintragsdaten unserer Ansicht zur Verfügung stellen.
class SurveyEntriesController params[:choice]) redirect_to '/' endend
Schließlich sollten wir unsere Indexansicht für Umfrageeinträge aktualisieren, um die Ergebnisse der Umfrageeinträge und die Programmiersprachenoptionen anzuzeigen.
Sobald wir eine Tabelle in unserer HTML-Seite haben, können wir die progressive Verbesserung verwenden und CSS anwenden, um das Erscheinungsbild zu verbessern und das Seitenlayout zu verbessern. Mit einem jQuery-Plug-In können wir die Ergebnisdaten auch optisch ansprechender gestalten, um die Tabellendaten in ein Diagramm zu konvertieren.
Um die Tabelle in ein Diagramm zu konvertieren, müssen wir die hinzufügen jQuery Bibliothek (jquery. com), die jQuery-Diagramm-Plug-In und rufen Sie einfach auf, um das Diagramm für die HTML-Seite zu erstellen:
Feinpunktstift für iPad 2
$(function(){ $(“#results”).chart();});
Im Formular haben wir für jede Auswahl eine Schaltfläche. Wenn Sie darauf klicken, wird der Wert der Schaltfläche an unseren Server gesendet. In Rails sieht der Controller-Code zum Empfangen der Abstimmung wie folgt aus:
def create SurveyEntry.create(:choice => params[:choice]) redirect_to '/' end
Das SurveyEntry.create Methode wird von der geerbt Aktiver Rekord Klasse ( ar.rubyonrails.org/ ) und behält die Auswahl für die Datenbank bei. Aktiver Rekord kann auch unsere Formularvalidierung für uns übernehmen, aber darauf werden wir hier nicht eingehen.
Sobald der Datensatz gespeichert wurde, wird der Benutzer zur Ursprungsseite und zur Indexaktion umgeleitet. Die Formularübermittlung könnte auch mithilfe einer Ajax-Anfrage schrittweise verbessert werden, die Standardformularübermittlung reicht jedoch vorerst aus. Wir werden die Leute nicht davon abhalten, mehr als einmal abzustimmen, aber eine echte Bewerbung würde es wahrscheinlich tun.
Wir fügen der Anwendung Echtzeit-Updates hinzu, indem wir eine WebSocket-Verbindung einführen, damit wir die Umfrageergebnisse vom Server an alle verbundenen Browser übertragen können, wenn sie sich ändern. In diesem Beispiel verwenden wir Pusher für den WebSocket-Server, da die Konfiguration eines Socket-Servers den Rahmen dieses Lernprogramms sprengt.
Pusher bietet auch eine REST-API, mit der Sie Nachrichten aus der vorhandenen Sprache Ihrer Wahl an verbundene Clients senden können. Viele der Prinzipien von Pusher können jedoch problemlos auf eine allgemeinere WebSocket-Installation angewendet werden. Pusher verfügt über kostenlose Sandbox-Konten, mit denen Sie die Funktionalität testen können. Wenn Sie also dieses Beispiel ausprobieren möchten, müssen Sie sich dort anmelden.
Diese WebSocket-Integration besteht aus zwei Teilen:
Als erstes müssen wir eine WebSocket-Verbindung zum Pusher-Server herstellen. Pusher verfügt über eine JavaScript-Bibliothek, die dies für Sie erledigt. Sie müssen lediglich JavaScript in Ihre Seite einfügen und ein neues Pusher-Objekt mit Ihrem öffentlichen API-Schlüssel erstellen:
var pusher = new Pusher('YOUR_API_KEY');
Pusher verwendet auch das Konzept von Kanälen, sodass eine einzelne Verbindung viele verschiedene gefilterte Datenströme empfangen kann. In unserem Fall müssen wir nur einen Kanal für unsere Umfrage abonnieren, den wir anrufen werden Umfragekanal ::
var myChannel = pusher.subscribe('survey-channel');
Wenn unsere Anwendung mehrere Umfragen enthalten würde, könnten wir die Kanäle nach ihnen benennen. Hinter den Kulissen wird eine WebSocket-Verbindung zu Pusher hergestellt, und unsere Anwendung wartet jetzt auf Nachrichten.
Pusher verpackt Nachrichten in ein einfaches JSON-Protokoll, mit dem sie auf der Clientseite sehr einfach verarbeitet werden können. Wie wir bereits gesehen haben, hat ein WebSocket-Objekt im Allgemeinen nur einen Ereignis-Listener: onMessage und alles, was über eine einfache Anwendung hinausgeht, wird schwierig zu verwalten. Das folgende Beispiel zeigt dies anhand eines hypothetischen Szenarios, in dem Elemente zu einer Liste hinzugefügt werden:
var ws = new WebSocket('ws://ws.example.com')ws.onMessage(function(data){ $('#myList').append(data);});
Wenn Sie in der Lage sein möchten, Elemente zu berücksichtigen, die aus der Liste entfernt oder aktualisiert werden mussten, muss das Datenobjekt überprüft werden, um herauszufinden, ob das Ereignis anzeigt, dass ein Element hinzugefügt, aktualisiert oder entfernt wurde, und Ihr Code könnte komplizierter werden.
Wir nennen an Pusher gesendete Nachrichten 'Ereignisse' und sie ähneln der ereignisreichen UI-Programmierung, mit der Sie möglicherweise in JavaScript vertraut sind. Wenn sich beispielsweise eine Maus bewegt, wird a ausgelöst Mausbewegung Ereignis mit Daten über die Position des Cursors.
Wenn mit Pusher ein Ereignis auf Ihrem Server auftritt (z. B. wenn jemand einen Umfrageeintrag registriert), wird dieses Ereignis an den verbundenen Client gesendet (diesen Servercode wird später hinzugefügt).
Sie können Ihre eigenen Namenskonventionen verwenden, um verschiedene Ereignisse zu behandeln. In unserem Beispiel sind wir an ein Ereignis namens gebunden Daten geändert , die uns neue Daten zu Umfrageergebnissen liefern wird. In unserem JavaScript wird es so aussehen:
myChannel.bind('data-changed', function(data){ updateResults(data) }); function updateResults(data){ var tbody = jQuery('#results tbody'); var html = ''; for (var i=0; i < data.length; i++) { html += '' + data[i].title + ' ' + '' + data[i].votes + ' '; } tbody.html(html); jQuery('.chartscontainer').remove(); // remove old chart jQuery('#results').charts(); // redraw }
Dieser Code aktualisiert den HTML-Code des Tabellenkörpers, entfernt das aktuelle Diagramm und erstellt ein neues für die empfangenen Daten. Wir können auch ein jQuery Notice Plug-In verwenden ( code.google.com/p/jquery-notice/ ) innerhalb der updateResults Funktion, um zu überprüfen, ob der Benutzer sieht, dass die Ergebnisse aktualisiert wurden.
function updateResults(data){ jQuery.noticeAdd({ text: 'Results updated', stay: false }); var tbody = jQuery('#results tbody'); var html = ''; for (var i=0; i < data.length; i++) { html += '' + data[i].title + ' ' + '' + data[i].votes + ' '; } tbody.html(html); jQuery('.chartscontainer').remove(); // remove old chart jQuery('#results').charts(); // show updated chart }
Wir haben jetzt eine Möglichkeit, mit neuen Daten umzugehen, sobald sie eingehen, aber wir müssen auch ein wenig Code in unsere Serveranwendung schreiben, die sie sendet. Da unsere Anwendung in Ruby geschrieben ist, können wir den Pusher installieren RubyGem , was uns dabei helfen wird. Es gibt viele Bibliotheken in verschiedenen Sprachen, mit denen Sie kommunizieren können Pusher . In unserem Fall müssen wir den Edelstein nur mit installieren Edelstein Schieber installieren und fordern Sie es in unserem Code. Ein einfacher Ort, um dies aufzunehmen, ist in config / environment.rb , wo Sie auch Ihre Pusher-Anmeldeinformationen eingeben können:
require 'pusher' Pusher.app_id = 'YOUR APP ID' Pusher.key = 'YOUR KEY' Pusher.secret = 'YOUR SECRET'
Stellen Sie sicher, dass die Gem-Datei so aktualisiert wurde, dass sie auch den Drücker enthält:
Amnesie die dunkle Abstammung Cover Art
gem ‘pusher’
In der Steuerung, in der wir zuvor die Ergebnisse in die Datenbank geschrieben haben, fügen wir jetzt eine Zeile hinzu, die die aktualisierten Umfragedaten durch Auslösen eines Ereignisses an alle verbundenen Clients sendet. Wir haben bereits den Kanal eingerichtet, an den wir dies senden, und den Namen des Ereignisses, das wir verwenden werden:
def createSurveyEntry.create(:choice => params[:choice])Pusher['survey-channel'].trigger('data-changed',SurveyEntry.get_results.to_json) redirect_to '/' end
Jetzt kommt das lustige Stück. Öffnen Sie die Umfrageanwendung in zwei Browsern und registrieren Sie einige Stimmen im ersten Fenster. In der Sekunde, in der eine Abstimmung eingegangen ist, wird ein Hinweis angezeigt, und die Grafik wird neu gezeichnet. Dies ist ein ziemlich grobes Beispiel, aber es zeigt einen Teil der Leistungsfähigkeit dieser Technologie.
In diesem Tutorial haben wir zunächst eine einfache Ruby-Umfrageanwendung erstellt. Wir haben das grundlegende Erscheinungsbild der Anwendung durch schrittweise Verbesserung durch Anwendung von CSS und einer jQuery-Diagrammvisualisierung verbessert. Anschließend haben wir die Benutzererfahrung weiter verbessert, indem wir der Anwendung mithilfe von HTML5 WebSockets und Pusher Echtzeitfunktionen hinzugefügt haben.
Ich bin mir sicher, dass dieses Tutorial die Leistungsfähigkeit von HTML5-WebSockets gezeigt hat und wie einfach es sein kann, einer vorhandenen App Echtzeitfunktionen hinzuzufügen oder vom ersten Tag an Echtzeitfunktionen in Ihrer App zu aktivieren. In diesem Tutorial haben wir die Kommunikation zwischen Server und Client demonstriert. Beachten Sie, dass WebSockets eine bidirektionale Kommunikation ermöglichen. Ich bin sehr gespannt auf diese Technologie und habe bereits viele großartige Beispiele dafür gesehen, wie sie verwendet werden kann ( pusher.com/demos ), aber die Technologie ist noch jung und ich bin überzeugt, dass wir eine neue Generation von Web-Apps und Spielen sehen werden, die auf HTML5 WebSockets und seinen bidirektionalen Kommunikationsfunktionen basieren.