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:
TCP | UDP | SCTP | |
Zuverlässigkeit | Zuverlässig | Unzuverlässig | Konfigurierbar |
Lieferservice | Bestellt | Unsortiert | Konfigurierbar |
Übertragung | Byteorientiert | Nachrichtenorientiert | Nachrichtenorientiert |
Ablaufsteuerung | Ja | Nein | Ja |
Überlastungssteuerung | Ja | Nein | Ja |
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 nichtmaxPacketLifeTime
: die maximale Zeit für den Versuch, eine fehlgeschlagene Nachricht noch einmal zu sendenmaxRetransmits
: die maximale Anzahl der Versuche, eine fehlgeschlagene Nachricht noch einmal zu sendenprotocol
: ermöglicht die Verwendung eines Subprotokolls, das Metainformationen für die App bereitstelltnegotiated
: 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 mitnegotiated
verwendet werden kann, wenn sie auftrue
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:
- Datei in JavaScript mit der File API auslesen.
- Stellen Sie mit
RTCPeerConnection
eine Peer-Verbindung zwischen Clients her. - 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.