WebRTC - Envío de mensajes

Ahora creemos un ejemplo simple. En primer lugar, ejecute el servidor de señalización que creamos en el tutorial "servidor de señalización" a través de "servidor de nodo".

Habrá tres entradas de texto en la página, una para un inicio de sesión, otra para un nombre de usuario y otra para el mensaje que queremos enviar al otro par. Cree un archivo index.html y agregue el siguiente código:

<html lang = "en"> 
   <head> 
      <meta charset = "utf-8" /> 
   </head>
	
   <body> 
      <div> 
         <input type = "text" id = "loginInput" /> 
         <button id = "loginBtn">Login</button> 
      </div> 
		
      <div> 
         <input type = "text" id = "otherUsernameInput" /> 
         <button id = "connectToOtherUsernameBtn">Establish connection</button> 
      </div> 
		
      <div> 
         <input type = "text" id = "msgInput" /> 
         <button id = "sendMsgBtn">Send text message</button> 
      </div> 
		
      <script src = "client.js"></script>
   </body>
	
</html>

También agregamos tres botones para iniciar sesión, establecer una conexión y enviar un mensaje. Ahora cree un archivo client.js y agregue el siguiente código:

var connection = new WebSocket('ws://localhost:9090'); 
var name = "";

var loginInput = document.querySelector('#loginInput'); 
var loginBtn = document.querySelector('#loginBtn'); 

var otherUsernameInput = document.querySelector('#otherUsernameInput'); 
var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn'); 
var msgInput = document.querySelector('#msgInput'); 
var sendMsgBtn = document.querySelector('#sendMsgBtn'); 
var connectedUser, myConnection, dataChannel;
  
//when a user clicks the login button 
loginBtn.addEventListener("click", function(event) { 
   name = loginInput.value; 
	
   if(name.length > 0) { 
      send({ 
         type: "login", 
         name: name 
      }); 
   } 
}); 
 
//handle messages from the server 
connection.onmessage = function (message) { 
   console.log("Got message", message.data); 
   var data = JSON.parse(message.data); 
	
   switch(data.type) { 
      case "login": 
         onLogin(data.success); 
         break; 
      case "offer": 
         onOffer(data.offer, data.name); 
         break; 
      case "answer":
         onAnswer(data.answer); 
         break; 
      case "candidate": 
         onCandidate(data.candidate); 
         break; 
      default: 
         break; 
   } 
}; 
 
//when a user logs in 
function onLogin(success) { 

   if (success === false) { 
      alert("oops...try a different username"); 
   } else { 
      //creating our RTCPeerConnection object 
      var configuration = { 
         "iceServers": [{ "url": "stun:stun.1.google.com:19302" }] 
      }; 
		
      myConnection = new webkitRTCPeerConnection(configuration, { 
         optional: [{RtpDataChannels: true}] 
      }); 
		
      console.log("RTCPeerConnection object was created"); 
      console.log(myConnection); 
  
      //setup ice handling 
      //when the browser finds an ice candidate we send it to another peer 
      myConnection.onicecandidate = function (event) { 
		
         if (event.candidate) { 
            send({ 
               type: "candidate", 
               candidate: event.candidate 
            });
         } 
      }; 
		
      openDataChannel();
		
   } 
};
  
connection.onopen = function () { 
   console.log("Connected"); 
}; 
 
connection.onerror = function (err) { 
   console.log("Got error", err); 
};
  
// Alias for sending messages in JSON format 
function send(message) { 
   if (connectedUser) { 
      message.name = connectedUser; 
   }
	
   connection.send(JSON.stringify(message)); 
};

Puede ver que establecemos una conexión de socket a nuestro servidor de señalización. Cuando un usuario hace clic en el botón de inicio de sesión, la aplicación envía su nombre de usuario al servidor. Si el inicio de sesión es exitoso, la aplicación crea el objeto RTCPeerConnection y configura un controlador de candidatos de hielo que envía todos los candidatos de hielo encontrados al otro par. También ejecuta la función openDataChannel () que crea un dataChannel. Tenga en cuenta que al crear el objeto RTCPeerConnection, el segundo argumento en el constructor es opcional: [{RtpDataChannels: true}] es obligatorio si está utilizando Chrome u Opera. El siguiente paso es crear una oferta para el otro compañero. Agregue el siguiente código a su archivo client.js

//setup a peer connection with another user 
connectToOtherUsernameBtn.addEventListener("click", function () {
  
   var otherUsername = otherUsernameInput.value;
   connectedUser = otherUsername;
	
   if (otherUsername.length > 0) { 
      //make an offer 
      myConnection.createOffer(function (offer) { 
         console.log(); 
			
         send({ 
            type: "offer", 
            offer: offer 
         }); 
			
         myConnection.setLocalDescription(offer); 
      }, function (error) { 
         alert("An error has occurred."); 
      }); 
   } 
});
  
//when somebody wants to call us 
function onOffer(offer, name) { 
   connectedUser = name; 
   myConnection.setRemoteDescription(new RTCSessionDescription(offer));
	
   myConnection.createAnswer(function (answer) { 
      myConnection.setLocalDescription(answer); 
		
      send({ 
         type: "answer", 
         answer: answer 
      }); 
		
   }, function (error) { 
      alert("oops...error"); 
   }); 
}

//when another user answers to our offer 
function onAnswer(answer) { 
   myConnection.setRemoteDescription(new RTCSessionDescription(answer)); 
}
  
//when we got ice candidate from another user 
function onCandidate(candidate) { 
   myConnection.addIceCandidate(new RTCIceCandidate(candidate)); 
}

Puede ver que cuando un usuario hace clic en el botón "Establecer conexión", la aplicación hace una oferta de SDP al otro par. También configuramos los controladores onAnswer y onCandidate . Finalmente, implementemos la función openDataChannel () que crea nuestro dataChannel. Agregue el siguiente código a su archivo client.js :

//creating data channel 
function openDataChannel() { 

   var dataChannelOptions = { 
      reliable:true 
   }; 
	
   dataChannel = myConnection.createDataChannel("myDataChannel", dataChannelOptions);
	
   dataChannel.onerror = function (error) { 
      console.log("Error:", error); 
   };
	
   dataChannel.onmessage = function (event) { 
      console.log("Got message:", event.data); 
   };  
}
  
//when a user clicks the send message button 
sendMsgBtn.addEventListener("click", function (event) { 
   console.log("send message");
   var val = msgInput.value; 
   dataChannel.send(val); 
});

Aquí creamos el canal de datos para nuestra conexión y agregamos el controlador de eventos para el botón "enviar mensaje". Ahora abra esta página en dos pestañas, inicie sesión con dos usuarios, establezca una conexión e intente enviar mensajes. Debería verlos en la salida de la consola. Tenga en cuenta que el ejemplo anterior se prueba en Opera.

Ahora puede ver que RTCDataChannel es una parte extremadamente poderosa de la API de WebRTC. Hay muchos otros casos de uso para este objeto, como los juegos de igual a igual o el intercambio de archivos basado en torrents.