Daten zwischen Browsern mit WebRTC-Datenkanälen senden

Das Senden von Daten zwischen zwei Browsern für Kommunikation, Spiele oder Dateiübertragungen kann ziemlich aufwendig sein. Dazu muss ein Server für die Weiterleitung von Daten eingerichtet und kostenpflichtig sein. Dieser muss möglicherweise auf mehrere Rechenzentren skaliert werden. In diesem Szenario besteht das Potenzial für eine hohe Latenz und es ist schwierig, die Daten zu schützen.

Diese Probleme lassen sich umgehen, indem Sie die RTCDataChannel API von WebRTC verwenden, um Daten direkt von einem Peer zum anderen zu übertragen. In diesem Artikel werden die Grundlagen der Einrichtung und Verwendung von Datenkanälen sowie die häufigsten Anwendungsfälle im Web behandelt.

Warum ein weiterer Datenkanal?

Wir nutzen WebSocket, AJAX und Server Sent Events. Warum brauchen wir einen weiteren Kommunikationskanal? WebSocket funktioniert bidirektional, aber alle diese Technologien sind für die Kommunikation mit oder von einem Server ausgelegt.

RTCDataChannel verfolgt einen anderen Ansatz:

  • Es funktioniert mit der RTCPeerConnection API, die Peer-to-Peer-Verbindungen ermöglicht. Dies kann zu einer geringeren Latenz führen – kein Zwischenserver und weniger „Hops“.
  • RTCDataChannel verwendet das Stream Control Transmission Protocol (SCTP), was eine konfigurierbare Übermittlungssemantik für die Zustellung außerhalb der Reihenfolge und die Konfiguration zur erneuten Übertragung ermöglicht.

RTCDataChannel ist jetzt mit SCTP-Unterstützung für Computer und Android in Google Chrome, Opera und Firefox verfügbar.

Ein wichtiger Hinweis: Signalisierung, STUN und DREHEN

WebRTC ermöglicht Peer-to-Peer-Kommunikation, benötigt aber weiterhin Server für die Signalisierung, um Medien- und Netzwerkmetadaten für das Bootstrapping einer Peer-Verbindung auszutauschen.

WebRTC unterstützt NATs und Firewalls mit:

  • Das ICE-Framework, um den bestmöglichen Netzwerkpfad zwischen Peers zu etablieren.
  • STUN-Server, um eine öffentlich zugängliche IP-Adresse und einen öffentlich zugänglichen Port für jeden Peer zu ermitteln.
  • Turn-Server, wenn eine direkte Verbindung fehlschlägt und Daten-Relais erforderlich ist.

Weitere Informationen dazu, wie WebRTC mit Servern für Signale und Netzwerke funktioniert, finden Sie unter WebRTC in der realen Welt: STUN, Turn und signaling.

Die Funktionen

Die RTCDataChannel API unterstützt einen flexiblen Satz von Datentypen. Die API ist darauf ausgelegt, WebSocket exakt nachzuahmen, und RTCDataChannel unterstützt Strings sowie einige Binärtypen in JavaScript, z. B. Blob, ArrayBuffer und ArrayBufferView. Diese Typen können bei der Dateiübertragung und beim Spielen im Mehrspielermodus nützlich sein.

RTCDataChannel kann im unzuverlässigen und ungeordneten Modus (Analog zu User Datagram Protocol oder UDP), im zuverlässigen und geordneten Modus (analog zu Transmission Control Protocol oder TCP) und im teilweisen zuverlässigen Modus funktionieren:

  • Der Modus „Zuverlässige und geordnete Reihenfolge“ garantiert die Übertragung von Nachrichten sowie die Reihenfolge, in der sie zugestellt werden. Das ist mit zusätzlichem Aufwand verbunden und kann den Modus verlangsamen.
  • Der unzuverlässige und ungeordnete Modus garantiert nicht, dass jede Nachricht auf der anderen Seite ankommt oder in welcher Reihenfolge sie dorthin gelangen. Dadurch entfällt der Aufwand und der Modus funktioniert viel schneller.
  • Der teilweise zuverlässige Modus garantiert die Übertragung von Nachrichten unter einer bestimmten Bedingung, z. B. eine Zeitüberschreitung für die erneute Übertragung oder eine maximale Anzahl von Neuübertragungen. Die Reihenfolge der Nachrichten ist ebenfalls konfigurierbar.

Die Leistung der ersten beiden Modi ist ungefähr gleich, wenn keine Paketverluste auftreten. Im zuverlässigen und geordneten Modus führt ein verlorenes Paket jedoch dazu, dass andere Pakete im Hintergrund blockiert werden. Das verlorene Paket kann dann veraltet sein, bis es erneut übertragen wird und eintrifft. Es ist natürlich möglich, mehrere Datenkanäle innerhalb derselben Anwendung zu verwenden, jeder mit eigener zuverlässiger oder unzuverlässiger Semantik.

Hier ist eine hilfreiche Tabelle des High Performance Browser Networking von Ilya Grigorik:

TCPUDPSCTP
ZuverlässigkeitZuverlässigUnzuverlässigKonfigurierbar
LieferserviceBestelltUnsortiertKonfigurierbar
ÜbertragungByteorientiertNachrichtenorientiertNachrichtenorientiert
AblaufsteuerungJaNeinJa
ÜberlastungssteuerungJaNeinJa

Als Nächstes erfahren Sie, wie Sie RTCDataChannel für den zuverlässigen und geordneten oder unzuverlässigen und ungeordneten Modus konfigurieren.

Datenkanäle konfigurieren

Es gibt mehrere einfache Demos von RTCDataChannel online:

In diesen Beispielen stellt der Browser eine Peer-Verbindung zu sich selbst her, erstellt dann einen Datenkanal und sendet eine Nachricht über die Peer-Verbindung. Anschließend wird ein Datenkanal erstellt und die Nachricht wird über die Peer-Verbindung gesendet. Schließlich wird Ihre Nachricht im Feld auf der anderen Seite der Seite angezeigt.

Der Code für den Einstieg ist kurz:

const peerConnection = new RTCPeerConnection();

// Establish your peer connection using your signaling channel here
const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};

Das dataChannel-Objekt wird über eine bereits hergestellte Peer-Verbindung erstellt. Sie kann vor oder nach der Signalisierung erstellt werden. Anschließend übergeben Sie ein Label, um diesen Channel von anderen zu unterscheiden, sowie eine Reihe optionaler Konfigurationseinstellungen:

const dataChannelOptions = {
  ordered: false, // do not guarantee order
  maxPacketLifeTime: 3000, // in milliseconds
};

Es ist auch möglich, eine maxRetransmits-Option hinzuzufügen, also die Anzahl der Versuche, bis der Vorgang fehlschlägt. Sie können jedoch nur maxRetransmits oder maxPacketLifeTime angeben, nicht beides. Legen Sie für UDP-Semantik maxRetransmits auf 0 und ordered auf false fest. Weitere Informationen finden Sie in den IETF-RFCs: Stream Control Transmission Protocol und Stream Control Transmission Protocol Partial Reliability Extension.

  • ordered: gibt an, ob der Datenkanal die Reihenfolge garantieren soll oder nicht
  • maxPacketLifeTime: die maximale Zeit für den Versuch, eine fehlgeschlagene Nachricht noch einmal zu senden
  • maxRetransmits: die maximale Anzahl der Versuche, eine fehlgeschlagene Nachricht noch einmal zu senden
  • protocol: ermöglicht die Verwendung eines Subprotokolls, das Metainformationen für die App bereitstellt
  • negotiated: Wenn dieser Wert auf „true“ gesetzt ist, wird die automatische Einrichtung eines Datenkanals auf dem anderen Peer entfernt. So können Sie auf der anderen Seite einen Datenkanal mit derselben ID erstellen.
  • id: Damit kannst du deine eigene ID für den Kanal angeben, die nur in Kombination mit negotiated verwendet werden kann, wenn sie auf true gesetzt ist.

Die einzigen Optionen, die die meisten Nutzer verwenden müssen, sind die ersten drei: ordered, maxPacketLifeTime und maxRetransmits. Mit SCTP, das jetzt von allen Browsern verwendet wird, die WebRTC unterstützen, gilt standardmäßig die Zuverlässigkeit und Reihenfolge. Die Verwendung von „unzuverlässig“ und „ungeordnet“ ist sinnvoll, wenn Sie die volle Kontrolle über die App-Ebene wünschen. In den meisten Fällen ist jedoch eine teilweise Zuverlässigkeit hilfreich.

Beachten Sie, dass RTCDataChannel wie bei WebSocket Ereignisse auslöst, wenn eine Verbindung hergestellt oder geschlossen wird oder Fehler auftreten, und wenn eine Nachricht vom anderen Peer empfangen wird.

Ist es sicher?

Die Verschlüsselung ist für alle WebRTC-Komponenten obligatorisch. Bei RTCDataChannel werden alle Daten mit Datagram Transport Layer Security (DTLS) geschützt. DTLS ist eine Ableitung von SSL. Das bedeutet, dass Ihre Daten so sicher sind wie jede standardmäßige SSL-basierte Verbindung. DTLS ist standardisiert und in alle Browser integriert, die WebRTC unterstützen. Weitere Informationen finden Sie im Wireshark-Wiki.

Ihre Sichtweise auf Daten ändern

Die Verarbeitung großer Datenmengen kann in JavaScript ein Problem sein. Wie die Entwickler von Sharefest betont haben, musste dies deshalb eine ganz neue Herangehensweise an die Daten erfordern. Wenn Sie eine Datei übertragen, die größer ist als der verfügbare Arbeitsspeicher, müssen Sie nach neuen Möglichkeiten suchen, diese Informationen zu speichern. Hier kommen Technologien wie die FileSystem API ins Spiel, wie Sie gleich sehen werden.

File-Sharing-App erstellen

Mit RTCDataChannel können Sie jetzt eine Webanwendung erstellen, mit der Dateien im Browser freigegeben werden können. Wenn du auf RTCDataChannel aufbaust, sind die übertragenen Dateidaten verschlüsselt und berühren nicht die Server eines App-Anbieters. Diese Funktion macht die WebRTC-Dateifreigabe in Verbindung mit der Möglichkeit, eine Verbindung zu mehreren Clients herzustellen, um schneller Daten zu teilen, zu einem sehr guten Kandidat für das Web.

Für eine erfolgreiche Überweisung sind mehrere Schritte erforderlich:

  1. Datei in JavaScript mit der File API auslesen.
  2. Stellen Sie mit RTCPeerConnection eine Peer-Verbindung zwischen Clients her.
  3. Erstellen Sie mit RTCDataChannel einen Datenkanal zwischen Clients.

Beim Senden von Dateien über RTCDataChannel sind mehrere Punkte zu beachten:

  • Dateigröße:Wenn die Dateigröße relativ klein ist und als ein Blob gespeichert und geladen werden kann, können Sie die Datei mithilfe der File API in den Speicher laden und dann unverändert über einen zuverlässigen Kanal senden. Beachten Sie jedoch, dass Browser die maximale Übertragungsgröße begrenzt. Mit zunehmender Dateigröße wird es schwieriger. Wenn ein Aufteilungsmechanismus erforderlich ist, werden Dateiblöcke geladen und zusammen mit chunkID-Metadaten an einen anderen Peer gesendet, damit der Peer sie erkennen kann. Beachten Sie, dass Sie in diesem Fall die Blöcke auch zuerst im Offline-Speicher speichern müssen (z. B. mit der FileSystem API) und erst dann auf der Festplatte des Nutzers speichern, wenn die Datei komplett vorhanden ist.
  • Chunk-Größe:Dies sind die kleinsten „Atome“ der Daten für Ihre App. Die Chunk-Chunk-Größe ist erforderlich, da derzeit eine Beschränkung für die Sendegröße existiert. Dies wird jedoch in einer zukünftigen Version von Datenkanälen behoben. Die aktuelle Empfehlung für eine maximale Chunk-Größe beträgt 64 KiB.

Sobald die Datei vollständig auf die andere Seite übertragen wurde, kann sie mithilfe eines Anchor-Tags heruntergeladen werden:

function saveFile(blob) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

Diese Dateifreigabe-Apps auf PubShare und GitHub verwenden dieses Verfahren. Beide sind Open Source und bieten eine gute Grundlage für eine auf RTCDataChannel basierende Filesharing-App.

Was können Sie also tun?

RTCDataChannel eröffnet neue Möglichkeiten, Apps für die Dateifreigabe, den Mehrspielermodus und die Inhaltsübermittlung zu entwickeln.

  • Peer-to-Peer-Dateifreigabe wie zuvor beschrieben
  • Spiele für mehrere Spieler in Kombination mit anderen Technologien wie WebGL, wie in BananaBread von Mozilla
  • Inhaltsübermittlung durch PeerCDN neu erfunden, ein Framework, das Web-Assets über Peer-to-Peer-Datenkommunikation bereitstellt

Apps anders entwickeln

Sie können jetzt über RTCDataChannel ansprechendere Apps bereitstellen, indem Sie leistungsstarke Verbindungen mit niedriger Latenz verwenden. Frameworks wie PeerJS und das PubNub WebRTC SDK erleichtern die Implementierung von RTCDataChannel. Außerdem wird die API jetzt plattformübergreifend unterstützt.

Die Einführung von RTCDataChannel kann die Sichtweise auf die Datenübertragung im Browser verändern.

Weitere Informationen