Envoyer des données entre deux navigateurs pour la communication, les jeux ou le transfert de fichiers peut être un processus assez complexe. Vous devez configurer et payer un serveur pour relayer les données, et peut-être l'étendre à plusieurs centres de données. Dans ce scénario, la latence peut être élevée et il est difficile de préserver la confidentialité des données.
Ces problèmes peuvent être atténués en utilisant l'API RTCDataChannel
de WebRTC pour transférer des données directement d'un pair à un autre. Cet article explique les principes de base de la configuration et de l'utilisation des canaux de données, ainsi que les cas d'utilisation courants sur le Web aujourd'hui.
Pourquoi un autre canal de données ?
Il existe trois protocoles : WebSocket, AJAX et Server-Sent Events. Pourquoi avons-nous besoin d'un autre canal de communication ? WebSocket est bidirectionnel, mais toutes ces technologies sont conçues pour la communication vers ou depuis un serveur.
RTCDataChannel
adopte une approche différente :
- Il fonctionne avec l'API
RTCPeerConnection
, qui permet la connectivité peer-to-peer. Cela peut réduire la latence, car il n'y a pas de serveur intermédiaire et moins de "sauts". RTCDataChannel
utilise le protocole SCTP (Stream Control Transmission Protocol), qui permet de configurer la sémantique de distribution (distribution hors séquence et configuration de la retransmission).
RTCDataChannel
est désormais disponible avec la prise en charge de SCTP sur ordinateur et Android dans Google Chrome, Opera et Firefox.
Mise en garde: signalisation, STUN et TURN
WebRTC permet la communication peer-to-peer, mais il a toujours besoin de serveurs pour le signalement afin d'échanger des métadonnées multimédias et réseau pour démarrer une connexion peer-to-peer.
WebRTC gère les NAT et les pare-feu grâce aux éléments suivants :
- Le framework ICE pour établir le meilleur chemin réseau possible entre les pairs.
- Serveurs STUN pour vérifier une adresse IP et un port publiquement accessibles pour chaque pair.
- Serveurs TURN en cas d'échec de la connexion directe et de nécessité de transfert de données.
Pour en savoir plus sur le fonctionnement de WebRTC avec les serveurs pour la signalisation et la mise en réseau, consultez WebRTC dans le monde réel: STUN, TURN et signalisation.
Fonctionnalités
L'API RTCDataChannel
accepte un ensemble flexible de types de données. L'API est conçue pour imiter exactement WebSocket, et RTCDataChannel
accepte les chaînes ainsi que certains types binaires de JavaScript, tels que Blob, ArrayBuffer et ArrayBufferView. Ces types peuvent être utiles pour le transfert de fichiers et les jeux multijoueurs.
RTCDataChannel
peut fonctionner en mode non fiable et non ordonné (analogue au protocole UDP), en mode fiable et ordonné (analogue au protocole TCP) et en mode fiable partiel :
- Le mode fiable et ordonné garantit la transmission des messages, ainsi que l'ordre dans lequel ils sont distribués. Cela entraîne des coûts supplémentaires, ce qui peut ralentir ce mode.
- Le mode non fiable et non ordonné ne garantit pas que tous les messages parviennent à l'autre extrémité ni dans quel ordre. Cela élimine les coûts indirects, ce qui permet à ce mode de fonctionner beaucoup plus rapidement.
- Le mode fiable partiel garantit la transmission du message sous une condition spécifique, telle qu'un délai avant expiration de la retransmision ou un nombre maximal de retransmissions. L'ordre des messages est également configurable.
Les performances des deux premiers modes sont à peu près identiques lorsqu'il n'y a aucune perte de paquets. Toutefois, en mode fiable et ordonné, un paquet perdu entraîne le blocage d'autres paquets derrière lui, et le paquet perdu peut être obsolète au moment de sa retransmission et de son arrivée. Il est bien sûr possible d'utiliser plusieurs canaux de données dans la même application, chacun avec sa propre sémantique fiable ou non fiable.
Voici un tableau utile tiré de High Performance Browser Networking (Haute performance de la mise en réseau du navigateur) par Ilya Grigorik :
TCP | UDP | SCTP | |
Fiabilité | Fiable | Manque de fiabilité | Configurable |
Envoi | Date de la commande | Non trié | Configurable |
Transmission | Orienté octets | Communication orientée messages | Message-oriented |
Contrôle de flux | Oui | Non | Oui |
Contrôle de la congestion | Oui | Non | Oui |
Vous allez ensuite apprendre à configurer RTCDataChannel
pour utiliser les modes "fiable", "ordonné" ou "non fiable" et "non ordonné".
Configurer des canaux de données
Il existe plusieurs démonstrations simples de RTCDataChannel
en ligne:
- simpl.info
RTCDataChannel
- Exemples WebRTC Transmettre du texte
- Exemples WebRTC Transférer un fichier
Dans ces exemples, le navigateur établit une connexion d'appairage avec lui-même, puis crée un canal de données et envoie un message via la connexion appairée. Il crée ensuite un canal de données et envoie le message via la connexion peer. Enfin, votre message s'affiche dans le champ de l'autre côté de la page.
Le code de démarrage est court :
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");
};
L'objet dataChannel
est créé à partir d'une connexion peer déjà établie. Il peut être créé avant ou après la signalisation. Vous devez ensuite transmettre un libellé pour distinguer ce canal des autres et un ensemble de paramètres de configuration facultatifs:
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
Vous pouvez également ajouter une option maxRetransmits
(nombre de tentatives avant échec), mais vous ne pouvez spécifier que maxRetransmits ou maxPacketLifeTime, et non les deux. Pour la sémantique UDP, définissez maxRetransmits
sur 0
et ordered
sur false
. Pour en savoir plus, consultez les RFC IETF suivantes: Stream Control Transmission Protocol et Stream Control Transmission Protocol Partial Reliability Extension.
ordered
: indique si le canal de données doit garantir l'ordre ou nonmaxPacketLifeTime
: délai maximal pour tenter de retransmettre un message ayant échouémaxRetransmits
: nombre maximal de tentatives de retransmission d'un message ayant échouéprotocol
: permet d'utiliser un sous-protocole, qui fournit des métadonnées à l'applicationnegotiated
: si cette valeur est définie sur "true", la configuration automatique d'un canal de données sur l'autre paire est supprimée. Vous pouvez ainsi créer un canal de données avec le même ID de l'autre côté.id
: vous permet de fournir votre propre ID pour la chaîne, qui ne peut être utilisé qu'avecnegotiated
défini surtrue
.
La plupart des utilisateurs n'ont besoin que des trois premières options : ordered
, maxPacketLifeTime
et maxRetransmits
. Avec SCTP (maintenant utilisé par tous les navigateurs compatibles avec WebRTC), la fiabilité et l'ordre sont définis par défaut sur "true". Il est logique d'utiliser des éléments non fiables et non ordonnés si vous souhaitez un contrôle total depuis la couche application, mais dans la plupart des cas, une fiabilité partielle est utile.
Notez que, comme avec WebSocket, RTCDataChannel
déclenche des événements lorsqu'une connexion est établie, fermée ou en erreur, et lorsqu'il reçoit un message de l'autre paire.
Est-ce sûr ?
Le chiffrement est obligatoire pour tous les composants WebRTC. Avec RTCDataChannel
, toutes les données sont sécurisées par le protocole DTLS (Datagram Transport Layer Security). DTLS est un dérivé de SSL. Par conséquent, vos données seront aussi sécurisées que si vous utilisiez une connexion SSL standard. DTLS est standardisé et intégré à tous les navigateurs compatibles avec WebRTC. Pour en savoir plus, consultez le wiki Wireshark.
Changez votre façon de penser aux données
La gestion de grandes quantités de données peut être un problème dans JavaScript. Comme l'ont souligné les développeurs de Sharefest, cela a nécessité une nouvelle façon de penser les données. Si vous transférez un fichier dont la capacité est supérieure à la quantité de mémoire dont vous disposez, vous devez trouver de nouvelles façons d'enregistrer ces informations. C'est là que les technologies telles que l'API FileSystem entrent en jeu, comme vous le verrez ci-dessous.
Créer une application de partage de fichiers
RTCDataChannel
vous permet désormais de créer une application Web capable de partager des fichiers dans le navigateur. Si vous créez un élément sur la base de RTCDataChannel
, les données de fichier transférées sont chiffrées et ne touchent pas les serveurs d'un fournisseur d'applications. Cette fonctionnalité, combinée à la possibilité de se connecter à plusieurs clients pour un partage plus rapide, fait de WebRTC un candidat idéal pour le Web.
Plusieurs étapes sont nécessaires pour effectuer un transfert :
- Lire un fichier en JavaScript à l'aide de l'API File
- Établissez une connexion entre pairs entre les clients avec
RTCPeerConnection
. - Créez un canal de données entre les clients avec
RTCDataChannel
.
Plusieurs points sont à prendre en compte lorsque vous essayez d'envoyer des fichiers via RTCDataChannel
:
- Taille du fichier:si la taille du fichier est raisonnablement petite et peut être stockée et chargée en tant que blob, vous pouvez le charger en mémoire à l'aide de l'API File, puis l'envoyer tel quel via un canal fiable (mais gardez à l'esprit que les navigateurs imposent des limites à la taille maximale de transfert). Plus la taille de fichier est importante, plus la tâche devient ardue. Lorsqu'un mécanisme de segmentation est requis, les fragments de fichiers sont chargés et envoyés à un autre pair, accompagnés de métadonnées
chunkID
pour que le pair puisse les reconnaître. Notez que, dans ce cas, vous devez également enregistrer d'abord les segments dans un stockage hors connexion (par exemple, à l'aide de l'API FileSystem) et ne les enregistrer sur le disque de l'utilisateur que lorsque vous disposez du fichier dans son intégralité. - Taille de fragment : il s'agit des plus petits "atomes" de données de votre application. Le fractionnement est obligatoire, car il existe actuellement une limite de taille d'envoi (mais ce problème sera corrigé dans une prochaine version des canaux de données). La taille maximale de fragment recommandée est actuellement de 64 Kio.
Une fois le fichier entièrement transféré de l'autre côté, il peut être téléchargé à l'aide d'une balise d'ancrage :
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
Ces applications de partage de fichiers sur PubShare et GitHub utilisent cette technique. Ils sont tous deux Open Source et constituent une bonne base pour une application de partage de fichiers basée sur RTCDataChannel
.
Alors, que pouvez-vous faire ?
RTCDataChannel
ouvre de nouvelles voies pour créer des applications de partage de fichiers, de jeux multijoueurs et de diffusion de contenus.
- Partage de fichiers peer-to-peer tel que décrit précédemment
- Jeux multijoueurs associés à d'autres technologies, telles que WebGL, comme dans BananaBread de Mozilla
- La diffusion de contenu est réinventée par PeerCDN, un framework qui diffuse des éléments Web via une communication de données peer-to-peer.
Une nouvelle façon de créer des applications
Vous pouvez désormais proposer des applications plus attrayantes grâce à des connexions hautes performances et à faible latence via RTCDataChannel
. Les frameworks tels que PeerJS et le SDK WebRTC PubNub facilitent l'implémentation de RTCDataChannel
. L'API est désormais largement compatible avec les plates-formes.
L'avènement de RTCDataChannel
peut changer votre façon de penser le transfert de données dans le navigateur.