Working Hello World WebRTC DataChannel Exemples avec signalisation implémentée

L'intention est de devenir une publication de Community Wiki qui est mise à jour pour que les développeurs intéressés à implémenter la communication des messages JSON navigateur vers le navigateur (p2p) avec WebRTC DataChannels ont des exemples simples et fonctionnels.

WebRTC DataChannels sont expérimentaux et encore en version brouillon. Il semble que le Web soit actuellement un champ de mines d'exemples WebRTC périmés et encore plus si un développeur essaie d'apprendre l'API RTCDataChannel.

Les exemples simples mais fonctionnels de 1 page qui fonctionnent aujourd'hui sur les navigateurs compatibles WebRTC semblent très difficiles à trouver. Par exemple, certains exemples excluent une implémentation de signalisation, d' autres ne fonctionnent que pour un navigateur unique (par exemple Chrome-Chrome), beaucoup sont obsolètes en raison des récents changements d'API, et d' autres sont si complexes qu'ils constituent un obstacle à la mise en route.

Veuillez publier des exemples répondant aux critères suivants (si quelque chose n'est pas satisfait, veuillez préciser):

  1. Le code côté client est de 1 page (200 lignes ou moins)
  2. Le code côté serveur est de 1 page et la technologie est référencée (p. Ex. Node.js, php, python, etc.)
  3. Le mécanisme de signalisation est implémenté et la technologie de protocole est référencée (p. Ex. WebSockets, sondage long , GCM , etc.)
  4. Code de fonctionnement qui fonctionne avec le navigateur croisé (Chrome, Firefox, Opera et / ou Bowser )
  5. Options minimales, traitement des erreurs, abstraction , etc. – l'intention est un exemple élémentaire

Voici un exemple de travail qui utilise HTML5 WebSockets pour la signalisation et un backend node.js

Technologie de signalisation: WebSockets
Client: pure html/javascript
Serveur: node.js , ws
Dernière version testée sur: Firefox 40.0.2 , Chrome 44.0.2403.157 m , Opera 31.0.1889.174


Code client:

 <html> <head> </head> <body> <p id='msg'>Click the following in different browser windows</p> <button type='button' onclick='init(false)'>I AM Answerer Peer (click first)</button> <button type='button' onclick='init(true)'>I AM Offerer Peer</button> <script> (function() { var offererId = 'Gandalf', // note: client id conflicts can happen answererId = 'Saruman', // no websocket cleanup code exists ourId, peerId, RTC_IS_MOZILLA = !!window.mozRTCPeerConnection, RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.msRTCPeerConnection, RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.msRTCSessionDescription, RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.msRTCIceCandidate, rtcpeerconn = new RTCPeerConnection( {iceServers: [{ 'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]}, {optional: [{RtpDataChannels: false}]} ), rtcdatachannel, websocket = new WebSocket('ws://' + window.location.hostname + ':8000'), comready, onerror; window.init = function(weAreOfferer) { ourId = weAreOfferer ? offererId : answererId; peerId = weAreOfferer ? answererId : offererId; websocket.send(JSON.stringify({ inst: 'init', id: ourId })); if(weAreOfferer) { rtcdatachannel = rtcpeerconn.createDataChannel(offererId+answererId); rtcdatachannel.onopen = comready; rtcdatachannel.onerror = onerror; rtcpeerconn.createOffer(function(offer) { rtcpeerconn.setLocalDescription(offer, function() { var output = offer.toJSON(); if(typeof output === 'string') output = JSON.parse(output); // normalize: RTCSessionDescription.toJSON returns a json str in FF, but json obj in Chrome websocket.send(JSON.stringify({ inst: 'send', peerId: peerId, message: output })); }, onerror); }, onerror); } }; rtcpeerconn.ondatachannel = function(event) { rtcdatachannel = event.channel; rtcdatachannel.onopen = comready; rtcdatachannel.onerror = onerror; }; websocket.onmessage = function(input) { var message = JSON.parse(input.data); if(message.type && message.type === 'offer') { var offer = new RTCSessionDescription(message); rtcpeerconn.setRemoteDescription(offer, function() { rtcpeerconn.createAnswer(function(answer) { rtcpeerconn.setLocalDescription(answer, function() { var output = answer.toJSON(); if(typeof output === 'string') output = JSON.parse(output); // normalize: RTCSessionDescription.toJSON returns a json str in FF, but json obj in Chrome websocket.send(JSON.stringify({ inst: 'send', peerId: peerId, message: output })); }, onerror); }, onerror); }, onerror); } else if(message.type && message.type === 'answer') { var answer = new RTCSessionDescription(message); rtcpeerconn.setRemoteDescription(answer, function() {/* handler required but we have nothing to do */}, onerror); } else if(rtcpeerconn.remoteDescription) { // ignore ice candidates until remote description is set rtcpeerconn.addIceCandidate(new RTCIceCandidate(message.candidate)); } }; rtcpeerconn.onicecandidate = function (event) { if (!event || !event.candidate) return; websocket.send(JSON.stringify({ inst: 'send', peerId: peerId, message: {candidate: event.candidate} })); }; /** called when RTC signaling is complete and RTCDataChannel is ready */ comready = function() { rtcdatachannel.send('hello world!'); rtcdatachannel.onmessage = function(event) { document.getElementById('msg').innerHTML = 'RTCDataChannel peer ' + peerId + ' says: ' + event.data; } }; /** global error function */ onerror = websocket.onerror = function(e) { console.log('====== WEBRTC ERROR ======', arguments); document.getElementById('msg').innerHTML = '====== WEBRTC ERROR ======<br>' + e; throw new Error(e); }; })(); </script> </body> </html> 

Code côté serveur:

 var server = require('http').createServer(), express = require('express'), app = express(), WebSocketServer = require('ws').Server, wss = new WebSocketServer({ server: server, port: 8000 }); app.use(express.static(__dirname + '/static')); // client code goes in static directory var clientMap = {}; wss.on('connection', function (ws) { ws.on('message', function (inputStr) { var input = JSON.parse(inputStr); if(input.inst == 'init') { clientMap[input.id] = ws; } else if(input.inst == 'send') { clientMap[input.peerId].send(JSON.stringify(input.message)); } }); }); server.on('request', app); server.listen(80, YOUR_HOSTNAME_OR_IP_HERE, function () { console.log('Listening on ' + server.address().port) });