Envío de mensajes entre pares con PeerJS

Saludos, queridos lectores. En un artículo anterior, hablé sobre cómo hacer un marcador simple en un navegador usando PeerJS . Y hoy planeo considerar cómo intercambiar mensajes entre dos usuarios directamente sin demora.

A quien le importa Si está desarrollando un juego en línea en el que necesita un intercambio rápido de datos entre jugadores, entonces la mensajería directa es quizás lo que necesita.

Marcado e inicialización


Mostraré cómo funciona la tecnología, usando un ejemplo de un chat simple entre dos usuarios , y también te diré cómo adaptar el código para intercambiar datos del juego.

Comencemos con el marcado inicial y la inicialización del objeto par

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>PeerJS  </title> <script src="https://unpkg.com/peerjs@1.0.0/dist/peerjs.min.js"></script> </head> <body> <h3> ID: <span id=myid ></span></h3> <input id=otherPeerId type=text placeholder="otherPeerId" ><button onclick="connectToNode(document.getElementById('otherPeerId').value)"></button> <div id=messages style="width:400px;height:60vh; background:#ADD8E6;margin:5px;"> </div><br> <textarea id=mess style="width:400px;height:15vh" ></textarea><br> <button onclick="sendMess(document.getElementById('mess'))"></button> <script> var messList=[]; function addMess(mess) { messList.push(mess); document.getElementById('messages').innerHTML=messList.join(""); } var peer=new Peer(); // peer var conn; //,   peer.on('open', function(peerID) { document.getElementById('myid').innerHTML=peerID; }); </script> </body> 

En el encabezado conectamos PeerJS. ¿Qué papel juegan los elementos con índices myid y otherPeerId en el artículo de la convocatoria?

La matriz messList almacenará el feed de mensajes. La función addMess agregará elementos a esta matriz y enviará su contenido al contenedor de correspondencia.

Lo siguiente es la inicialización del objeto par, que también se describe en el último artículo .

Ahora un poco sobre las conexiones. Para establecer una conexión, es necesario que un participante, conociendo el ID de par de otro, inicie una conexión con él y el segundo reciba esta conexión.

Establecer una conexión


 peer.on('connection', function(c) { // ... conn=c; initConn(); }); function connectToNode(partnerPeer) { // ... conn = peer.connect(partnerPeer); conn.partnerPeer=partnerPeer; initConn(); } 

El evento 'conexión' para el objeto par ocurre en una conexión entrante. Y la función de conexión del objeto par establece tal conexión. En ambos casos, guardaremos el objeto de conexión en la variable conn . Dado que otras acciones con la conexión para el ejemplo de entrenamiento actual serán idénticas (aunque puede haber una diferencia en el proyecto de combate), puse initConn en una función separada.

 function initConn() { conn.on ('open', function () { //  addMess("<div><h4> </h4></div>"); conn.on ('data', function (data) { //  addMess("<div><b>: </b>"+data+"</div>"); }); }); conn.on('close',function() {addMess('----------- -------------');}); } 

Aquí colgamos 2 manejadores: para abrir y cerrar la conexión. En el controlador para abrir una conexión, agregamos el controlador para recibir datos, lo que agregará un mensaje entrante al contenedor de diálogo.

Solo queda implementar una función que enviará un mensaje presionando el botón Enviar , que:

  1. agrega un mensaje a su feed
  2. envía un mensaje al socio (método de envío del objeto de conexión)
  3. borra el campo de entrada del mensaje

     function sendMess(elem) { addMess("<div><b>: </b>"+elem.value+"</div>"); conn.send(elem.value); elem.value=""; } 

Adaptación para transferir datos del juego.


¿Qué se debe hacer para enviar de la misma manera, no texto sin formato, sino datos que deben intercambiarse durante los juegos? Nada realmente especial En JS, hay métodos JSON.stringify y JSON.parse que convierten un objeto en una cadena y viceversa. Simplemente envuelva su objeto de datos, convierta el objeto en una cadena (JSON.stringify) antes de enviarlo y convierta los datos recibidos en un objeto (JSON.parse) cuando se reciba

 // gameObject={x:2,y:5,...} conn.send(JSON.stringify(gameObject)); // conn.on ('data', function (data) { //  gameObject=JSON.parse(data); }); 

Por lo general, no se necesitan grandes cantidades de datos para enviar objetos del juego y mensajes de texto. Pero si va a reenviar el contenido de todo el contenedor en la página (un montón de código HTML), tenga en cuenta que es posible que una conexión grande no llegue sin cambios.

Por experiencia personal, diré: no debe reenviar mensajes de más de 10 KB (~ 10,000 caracteres) de esta manera. Es mejor escribir un mensaje de este tipo en un archivo temporal y enviar un comando al socio para que lea el código de este archivo (creo que entendió el punto).

Podríamos parar en esto, si no ...

Ruptura de conexión


Sí, esto está pasando. La razón de esto es Internet inestable. ¿Alguna vez sucedió que casi has ganado, pero la conexión se rompe y pierdes todo tu progreso? Para evitar esto, agreguemos un código que generará una conexión caída. Manejaremos el evento 'cerrar' para esto. Este evento ocurre si:

  1. la conexión se cerró intencionalmente
  2. la conexión se perdió debido a una mala conexión a internet o el socio simplemente cerró la pestaña

     conn.on('close',function() { setTimeout(function() { if(conn.partnerPeer) { var pp=conn.partnerPeer; conn = peer.connect(conn.partnerPeer); conn.partnerPeer=pp; initConn(); } else conn=null; } ,2000); addMess('----------- -------------'); }); 

Aquí, con un retraso de 2 segundos después de la desconexión, simplemente estamos tratando de establecer uno nuevo.

El partnerPeer del objeto conn está presente solo en el partner que estableció la conexión por primera vez, lo que significa que solo uno de los 2 lados de la conexión comenzará a restablecerse cuando se rompa.

Y ahora todo el código:

 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>PeerJS  </title> <script src="https://unpkg.com/peerjs@1.0.0/dist/peerjs.min.js"></script> </head> <body> <h3> ID: <span id=myid ></span></h3> <input id=otherPeerId type=text placeholder="otherPeerId" ><button onclick="connectToNode(document.getElementById('otherPeerId').value)"></button> <div id=messages style="width:400px;height:60vh; background:#ADD8E6;margin:5px;"> </div><br> <textarea id=mess style="width:400px;height:15vh" ></textarea><br> <button onclick="sendMess(document.getElementById('mess'))"></button> <script> var messList=[]; function addMess(mess) { messList.push(mess); document.getElementById('messages').innerHTML=messList.join(""); } var peer=new Peer(); var conn; //,   peer.on('open', function(peerID) { document.getElementById('myid').innerHTML=peerID; }); peer.on('connection', function(c) { // ... conn=c; initConn(); }); function connectToNode(partnerPeer) { // ... conn = peer.connect(partnerPeer); initConn(); } function initConn() { conn.on ('open', function () { //  addMess("<div><h4> </h4></div>"); conn.on ('data', function (data) { //  addMess("<div><b>: </b>"+data+"</div>"); }); }); conn.on('close',function() {addMess('----------- -------------');}); } function sendMess(elem) { addMess("<div><b>: </b>"+elem.value+"</div>"); conn.send(elem.value); elem.value=""; } </script> </body> 

Source: https://habr.com/ru/post/470189/


All Articles