Daten zwischen Browsern mit WebRTC-Datenkanälen senden

Das Senden von Daten zwischen zwei Browsern für Kommunikation, Gaming oder Dateiübertragung kann ein ziemlich aufwendiger Vorgang sein. Es ist erforderlich, einen Server zum Weiterleiten von Daten einzurichten und zu bezahlen und ihn gegebenenfalls auf mehrere Rechenzentren auszuweiten. In diesem Szenario kann es zu einer hohen Latenz kommen und es ist schwierig, die Daten zu schützen.

Diese Probleme können durch die Verwendung der RTCDataChannel API von WebRTC behoben werden, um Daten direkt von einem Peer an einen anderen zu übertragen. In diesem Artikel erfahren Sie, wie Sie Datenkanäle einrichten und verwenden, und welche Anwendungsfälle im Web derzeit häufig vorkommen.

Warum ein anderer Datenkanal?

Es gibt WebSocket, AJAX und Server Sent Events. Warum brauchen wir einen anderen Kommunikationskanal? WebSocket funktioniert bidirektional. Alle diese Technologien sind jedoch für die Kommunikation mit einem oder von einem Server vorgesehen.

RTCDataChannel verfolgt einen anderen Ansatz:

  • Sie funktioniert mit der RTCPeerConnection API, die eine Peer-to-Peer-Verbindung ermöglicht. Das kann zu einer geringeren Latenz führen, da es keinen Zwischenserver und weniger „Hops“ gibt.
  • RTCDataChannel verwendet das Stream Control Transmission Protocol (SCTP), das eine konfigurierbare Auslieferungssemantik – die Lieferung in einer anderen Reihenfolge und die Neuübertragung – ermöglicht.

RTCDataChannel ist jetzt mit SCTP-Unterstützung auf Computern und Android-Geräten in Google Chrome, Opera und Firefox verfügbar.

Achtung: Signalisierung, STUN und DREHEN

WebRTC ermöglicht die Peer-to-Peer-Kommunikation, benötigt aber trotzdem Server für die Signalisierung, um Medien- und Netzwerkmetadaten auszutauschen und eine Peer-Verbindung zu starten.

WebRTC handhabt NATs und Firewalls mit:

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

Weitere Informationen dazu, wie WebRTC mit Servern für die Signalisierung und Netzwerke funktioniert, finden Sie unter WebRTC in the real world: STUN, TURN, and signaling.

Die Funktionen

Die RTCDataChannel API unterstützt einen flexiblen Satz von Datentypen. Die API wurde entwickelt, um WebSocket genau nachzuahmen. RTCDataChannel unterstützt Strings sowie einige der Binärtypen in JavaScript, z. B. Blob, ArrayBuffer und ArrayBufferView. Diese Typen können bei der Dateiübertragung und bei Multiplayer-Spielen hilfreich sein.

RTCDataChannel kann im unzuverlässigen und ungeordneten Modus (analog zum User Datagram Protocol oder UDP), im zuverlässigen und geordneten Modus (ähnlich zum Transmission Control Protocol oder TCP) und im teilweise zuverlässigen Modus arbeiten:

  • Der zuverlässige und geordnete Modus garantiert die Übertragung von Nachrichten und die Reihenfolge, in der sie zugestellt werden. Dies führt zu zusätzlichem Overhead und kann diesen Modus verlangsamen.
  • Im Modus „Unzuverlässig und unsortiert“ kann nicht garantiert werden, dass jede Nachricht ankommt und in welcher Reihenfolge sie ankommt. Dadurch wird der Overhead reduziert, sodass dieser Modus viel schneller funktioniert.
  • Der bedingte Modus garantiert die Nachrichtenübertragung unter einer bestimmten Bedingung, z. B. einem Zeitlimit für die Wiederholungsübertragung oder einer maximalen Anzahl von Wiederholungsübertragungen. Die Sortierung 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 dahinter blockiert werden. Das verlorene Paket ist möglicherweise veraltet, wenn es noch einmal gesendet und ankommt. Es ist natürlich möglich, innerhalb derselben App mehrere Datenkanäle zu verwenden, die jeweils ihre eigenen zuverlässigen oder unzuverlässigen Semantiken haben.

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

TCPUDPSCTP
ZuverlässigkeitZuverlässigUnzuverlässigKonfigurierbar
LieferungBestelltUnsortiertKonfigurierbar
ÜbertragungByte-orientiertNachrichtenorientiertNachrichtenorientiert
AblaufsteuerungJaNeinJa
ÜberlastungssteuerungJaNeinJa

Als Nächstes erfahren Sie, wie Sie RTCDataChannel für den zuverlässigen und geordneten oder den 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. Es wird dann ein Datenkanal erstellt und die Nachricht über die Peer-Verbindung gesendet. Ihre Nachricht wird schließlich im Feld auf der anderen Seite der Seite angezeigt.

Der Code dafür 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 aus einer bereits hergestellten Peer-Verbindung erstellt. Sie kann vor oder nach der Signalisierung erstellt werden. Geben Sie dann ein Label ein, um diesen Kanal von anderen zu unterscheiden, und 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 (die Anzahl der Versuche, bevor ein Fehler auftritt). Sie können jedoch nur maxRetransmits oder maxPacketLifeTime angeben, nicht beides. Legen Sie für die UDP-Semantik maxRetransmits auf 0 und ordered auf false fest. Weitere Informationen finden Sie in den folgenden IETF-RFCs: Stream Control Transmission Protocol und Stream Control Transmission Protocol Partial Reliability Extension.

  • ordered: ob der Datenkanal die Reihenfolge garantieren soll oder nicht
  • maxPacketLifeTime: die maximale Zeit für den Versuch, eine fehlgeschlagene Nachricht noch einmal zu übertragen
  • maxRetransmits: Die maximale Anzahl der Wiederholungsversuche für eine fehlgeschlagene Nachricht
  • protocol: Ermöglicht die Verwendung eines Unterprotokolls, das Metainformationen für die App bereitstellt.
  • negotiated: Wenn diese Option auf „true“ gesetzt ist, wird die automatische Einrichtung eines Datenkanals auf der anderen Peer-Seite entfernt, sodass Sie auf der anderen Seite einen Datenkanal mit derselben ID erstellen können.
  • id: Hiermit können Sie eine eigene ID für den Kanal angeben, die nur in Kombination mit negotiated = true verwendet werden kann.

Die meisten Nutzer benötigen nur die ersten drei Optionen: ordered, maxPacketLifeTime und maxRetransmits. Bei SCTP (wird jetzt von allen Browsern verwendet, die WebRTC unterstützen) sind „zuverlässig“ und „geordnet“ standardmäßig aktiviert. Es ist sinnvoll, unsichere und ungeordnete Verbindungen zu verwenden, wenn Sie die vollständige Kontrolle über die App-Ebene haben möchten. In den meisten Fällen ist jedoch eine teilweise Zuverlässigkeit hilfreich.

Wie bei WebSocket löst RTCDataChannel Ereignisse aus, wenn eine Verbindung hergestellt oder geschlossen wird, Fehler auftreten oder 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. Ihre Daten sind also genauso sicher wie bei einer standardmäßigen SSL-basierten Verbindung. DTLS ist standardisiert und in allen Browsern 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 eine Herausforderung sein. Wie die Entwickler von Sharefest hervorhoben, erforderte dies eine neue Herangehensweise an Daten. Wenn Sie eine Datei übertragen, die größer ist als der verfügbare Arbeitsspeicher, müssen Sie sich neue Möglichkeiten überlegen, wie Sie diese Informationen speichern können. Hier kommen Technologien wie die FileSystem API ins Spiel, wie Sie gleich sehen werden.

App zur Dateifreigabe erstellen

Mit RTCDataChannel können Sie jetzt eine Webanwendung erstellen, die Dateien im Browser freigeben kann. Wenn Sie auf RTCDataChannel aufbauen, werden die übertragenen Dateidaten verschlüsselt und die Server eines App-Anbieters werden nicht verwendet. Diese Funktion in Kombination mit der Möglichkeit, eine Verbindung zu mehreren Clients herzustellen, um die Freigabe zu beschleunigen, macht die WebRTC-Dateifreigabe zu einem starken Kandidaten für das Web.

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

  1. Dateien in JavaScript mit der File API lesen
  2. Peer-Verbindung zwischen Clients mit RTCPeerConnection herstellen
  3. Erstellen Sie mit RTCDataChannel einen Datenkanal zwischen Clients.

Wenn Sie versuchen, Dateien über RTCDataChannel zu senden, sind mehrere Punkte zu beachten:

  • Dateigröße: Wenn die Dateigröße relativ klein ist und als einzelnes Blob gespeichert und geladen werden kann, können Sie sie mit der File API in den Arbeitsspeicher laden und dann unverändert über einen zuverlässigen Kanal senden. Beachten Sie jedoch, dass Browser die maximale Übertragungsgröße begrenzen. Je größer die Datei ist, desto schwieriger wird es. Wenn ein Chunking-Mechanismus erforderlich ist, werden Datei-Chunks geladen und zusammen mit chunkID-Metadaten an einen anderen Peer gesendet, damit dieser sie erkennen kann. In diesem Fall müssen Sie die Chunks zuerst im Offlinespeicher speichern (z. B. mit der FileSystem API) und erst dann auf dem Laufwerk des Nutzers, wenn Sie die Datei vollständig haben.
  • Chunk-Größe: Dies sind die kleinsten „Atome“ von Daten für Ihre App. Das Chunking ist erforderlich, da derzeit eine Beschränkung der Sendegröße gilt. Dies wird jedoch in einer zukünftigen Version von Datenkanälen behoben. Die aktuelle Empfehlung für die maximale Größe von Chunks beträgt 64 KiB.

Sobald die Datei vollständig auf die andere Seite übertragen wurde, kann sie mit einem Anker-Tag heruntergeladen werden:

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

Diese Methode wird von den Filesharing-Apps in PubShare und GitHub verwendet. Beide sind Open Source und bieten eine gute Grundlage für eine Dateifreigabe-App, die auf RTCDataChannel basiert.

Was können Sie also tun?

RTCDataChannel eröffnet neue Möglichkeiten, Apps für die Dateifreigabe, Multiplayer-Gaming und die Bereitstellung von Inhalten zu erstellen.

  • Peer-to-Peer-Dateifreigabe wie oben beschrieben
  • Mehrspielerspiele in Kombination mit anderen Technologien wie WebGL, wie in BananaBread von Mozilla
  • Die Content Delivery wird von PeerCDN neu erfunden, einem Framework, das Web-Assets über Peer-to-Peer-Datenkommunikation bereitstellt

Apps anders entwickeln

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

Die Einführung von RTCDataChannel kann die Art und Weise verändern, wie Sie die Datenübertragung im Browser betrachten.

Weitere Informationen