Îmblanzirea WebRTC cu PeerJS: realizarea unui joc web P2P simplu
Publicat: 2022-03-11WebRTC este o tehnologie care permite comunicarea în timp real între browsere web. Este relativ nou, iar definiția API este încă considerată o schiță. Împreună cu faptul că WebRTC nu este încă acceptat de toate browserele web majore (și printre cele care o fac, unele dintre ele nu acceptă fiecare caracteristică a acestei tehnologii), acest lucru face să fie relativ dificilă utilizarea WebRTC pentru orice aplicație esențială. . Sau așa ai crede!
De când a fost introdus pentru prima dată de Google în mai 2011, WebRTC a fost folosit în multe aplicații web moderne. Fiind o caracteristică de bază a multor browsere web moderne, aplicațiile web pot profita fără probleme de această tehnologie pentru a oferi o experiență îmbunătățită a utilizatorului în multe feluri. Aplicațiile de streaming video sau de conferințe care nu necesită pluginuri de browser umflate și care pot profita de rețelele peer-to-peer (P2P) (în timp ce nu transmit fiecare bit de date printr-un server) este doar o parte din toate lucrurile uimitoare pe care le au. poate fi realizat cu WebRTC.
În acest articol, vom arunca o privire asupra modului în care WebRTC poate fi utilizat pentru a crea un simplu joc web P2P al lui Connect Four. Pentru a rezolva diferitele margini aspre și diferențele de implementare ale WebRTC, vom folosi o bibliotecă JavaScript uimitoare: PeerJS.
Date prin WebRTC
Înainte de a începe, este important să înțelegem că WebRTC nu înseamnă doar transmiterea de fluxuri audio și video. De asemenea, oferă suport pentru canalele de date P2P. Aceste canale vin în două variante: fiabile și nesigure. După cum se poate ghici, canalele de date fiabile garantează că mesajele sunt livrate și sunt livrate în ordine, în timp ce canalele nesigure nu oferă astfel de garanții.
În plus, canalele de date WebRTC nu necesită o configurare specială a infrastructurii, în afară de ceea ce este necesar pentru o conexiune peer WebRTC tipică: un server de semnalizare pentru a coordona conexiunea dintre egali, un server STUN pentru a afla identitatea publică a colegilor și, opțional, un server TURN pentru a direcționa mesajele între egali dacă nu poate fi stabilită o conexiune directă între egali (de exemplu, când ambii egali sunt în spatele NAT-urilor). Dacă aceste acronime sună familiar, este pentru că WebRTC reutilizează tehnologiile existente ori de câte ori este posibil.
Acest lucru deschide ușa către mai multe cazuri de utilizare ale WebRTC, inclusiv, dar fără a se limita la jocuri multiplayer, livrarea de conținut și partajarea fișierelor. Din nou, totul fără a fi nevoie de vreun server intermediar și, prin urmare, cu latențe mai mici.
În jocul nostru simplu web, vom folosi un canal de date între două browsere web pentru a comunica mișcările jucătorului înainte și înapoi.
Faceți cunoștință cu PeerJS
PeerJS preia implementarea WebRTC în browserul dvs. și include un API simplu, consistent și elegant în jurul acestuia. Astupă diferite găuri în implementarea WebRTC a browserelor anterioare. De exemplu, în Chrome 30 sau mai vechi, erau disponibile numai canale de date nesigure. PeerJS, dacă ar fi configurat să utilizeze canale de date fiabile, ar folosi un shim pentru acele browsere mai vechi. Deși acest lucru nu ar fi la fel de performant ca implementarea nativă a canalelor de încredere, ar funcționa în continuare.
Cu PeerJS, identificarea colegilor este și mai simplă. Fiecare egal este identificat folosind doar un ID. Un șir pe care peer-ul îl poate alege singur sau poate avea un server să genereze unul. Deși WebRTC promite comunicare peer-to-peer, oricum aveți nevoie de un server pentru a acționa ca un broker de conexiune și a gestiona semnalizarea. PeerJS oferă o implementare open source a acestui server de broker de conexiune PeerJS Server (scris în Node.js), în cazul în care nu doriți să utilizați versiunea lor găzduită în cloud (care este gratuită chiar acum și vine cu unele limitări).
Connect Four Goes P2P
Acum că avem o sursă de încredere pentru a lucra cu WebRTC, adică PeerJS, să începem prin a crea o aplicație simplă Node.js/Express.
npm init npm install express --save npm install jade --save npm install peer --save
Vom folosi acest lucru numai pentru a găzdui serverul PeerJS și pentru a difuza o pagină și elemente front-end. Va trebui să difuzăm doar o singură pagină, iar aceasta va conține două secțiuni: un meniu principal simplu și o grilă Connect Four de 7 pe 6.
Serverul PeerJS
Găzduirea propriului nostru server PeerJS este foarte ușoară. Depozitul oficial de pe GitHub are chiar și un buton cu un singur clic pentru a implementa o instanță a serverului PeerJS pe Heroku.
În cazul nostru, vrem doar să creăm o instanță a ExpressPeerServer în aplicația noastră Node.js și să o servim la „/peerjs”:
var express = require('express') var app = express() // … Configure Express, and register necessary route handlers srv = app.listen(process.env.PORT) app.use('/peerjs', require('peer').ExpressPeerServer(srv, { debug: true }))
Client PeerJS
Cu serverul PeerJS în funcțiune, trecem la partea client. După cum sa discutat mai devreme, PeerJS identifică colegii cu ID-uri unice. Aceste ID-uri pot fi generate de PeerServer pentru fiecare peer în mod automat sau putem alege unul pentru fiecare peer în timp ce instanțiem obiecte Peer .
var peer = new Peer(id, options)
Aici, id -ul poate fi omis cu totul dacă dorim ca serverul să ne genereze unul. În cazul nostru, asta vom dori să facem. PeerServer se va asigura că ID-urile pe care le oferă sunt unice. Al doilea argument, opțiuni , este de obicei un obiect care conține cheie (cheia API, dacă utilizați PeerServer găzduit în cloud, sau gazdă , port , cale etc., în cazul în care găzduiți singur PeerServer).
var peer = new Peer({ host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs' })
Pentru a stabili o conexiune între doi colegi PeerJS, unul dintre egali trebuie să cunoască ID-ul celuilalt peer. De dragul de a menține lucrurile simple, în implementarea noastră a Connect Four prin WebRTC, vom cere jucătorului care începe jocul să-și împărtășească ID-ul de peer cu adversarul său. Cu ID-ul de peer de destinație cunoscut, un simplu apel la peer.connect(destId) este tot ceea ce vom avea nevoie:

var conn = peer.connect(destId)
Atât obiectul Peer , cât și obiectul DataConnection returnat de peer.connect(destId) emit câteva evenimente cu adevărat utile care merită ascultate. În scopul acestui tutorial, ne interesează în special evenimentul „date” al obiectului DataConnection și evenimentele „eroare” ale ambelor obiecte.
Pentru a trimite date la celălalt capăt al conexiunii, pur și simplu invocați conn.send(data) :
conn.send('hello')
Deși un pic exagerat pentru nevoile noastre de aici, PeerJS transmite date între egali după ce le codifică în format BinaryPack. Acest lucru permite colegilor să comunice șiruri, numere, matrice, obiecte și chiar blob-uri.
Pentru a primi date, pur și simplu ascultați evenimentul „date” pe conn :
conn.on('data', function(data) { // data === 'hello' })
Și cam de asta avem nevoie!
Logica jocului
Primului jucător, cel care începe un joc, i se arată ID-ul său de peer așa cum este generat de PeerJS, pe care îl poate împărtăși cu adversarul său. Odată ce un adversar se alătură jocului folosind ID-ul de egalitate al primului jucător, primul jucător are voie să facă o mișcare.
Connect Four, fiind un joc de reguli și mecanici simple, are un singur tip de mișcare: fiecare jucător, la rândul său, trebuie să aleagă o coloană și să arunce un disc în ea. Aceasta înseamnă că tot ce trebuie să comunice un om de egalitate este numărul coloanei în care jucătorul curent a ales să-și arunce discul. Vom transmite această informație ca o matrice cu două elemente: un șir „mutare” și un număr - 0- indice bazat al coloanei din stânga.
De fiecare dată când un jucător dă clic pe o coloană:
if(!turn) { // it is not the current player's turn return } var i // i = chosen column index if(grid[i].length == 6) { // the column doesn't have any more space available return } // track player's move locally grid[i].push(peerId) // end current player's turn turn = false conn.send(['move', i])
După ce trimitem aceste date de mișcare adversarului, actualizăm starea jocului la nivel local. Aceasta include determinarea dacă jucătorul actual a câștigat sau dacă jocul s-a încheiat la egalitate.
La capătul care primește aceste date de mutare:
if(turn) { // ignore incoming move data when it is the current player's turn return } var i = data[1] if(grid[i].length == 6) { // ignore incoming move data when it is invalid return } // track opponent's move locally grid[i].push(opponent.peerId) // activate current player's turn turn = true
Și, firește, după aceasta actualizăm starea jocului la nivel local, stabilim dacă adversarul a câștigat sau dacă jocul s-a încheiat la egalitate.
Observați cum trebuie să efectuăm verificări de sănătate pe datele primite. Acest lucru este important, deoarece cu jocurile bazate pe WebRTC, nu avem server intermediar și logica de joc bazată pe server care validează datele de mișcare.
Pentru a menține fragmentele simple, liniile de cod care actualizează interfața de utilizare au fost omise. Puteți găsi codul sursă complet pentru JavaScript pe partea clientului aici.
Conectarea totul
Pentru a le combina pe toate, creăm o pagină simplă cu două secțiuni. La încărcarea paginii, se afișează secțiunea care conține meniul principal, secțiunea care conține grila de joc este păstrată ascunsă.
section#menu div.animated.bounceIn div h1 Connect Four br div.no-support() div.alert.alert-warning p Unfortunately, your web browser does not <a href="http://iswebrtcreadyyet.com">support WebRTC</a> div a.btn.btn-primary.btn-lg(href='#start') Start | a.btn.btn-default.btn-lg(href='#join') Join section#game() div div h1 Connect Four br table.table.grid tbody for i in [0, 1, 2, 3, 4, 5] tr for j in [0, 1, 2, 3, 4, 5, 6] td div.slot br div.alert.alert-info p
A face aceste elemente DOM să arate frumos este dincolo de scopul acestui tutorial. Prin urmare, vom apela la însoțitorul nostru de încredere Bootstrap și vom face un stil ușor peste el.
Pe măsură ce primul jucător dă clic pe butonul „Start”, grila de joc este dezvăluită împreună cu ID-ul de peer al jucătorului. Jucătorul poate partaja apoi acest ID peer cu adversarul său.
Al doilea jucător poate face clic, apoi face clic pe butonul „Înscrieți-vă”, introduceți ID-ul de peer al primului jucător și începe jocul.
Încercând
Puteți încerca acest exemplu de aplicație la https://arteegee.herokuapp.com.
Sau puteți clona depozitul din GitHub, instalați dependențe NPM și încercați local:
git clone https://github.com/hjr265/arteegee.git cd arteegee npm install PORT=5000 npm start
Odată ce serverul rulează, puteți să vă direcționați browserul web către http://localhost:5000, să începeți un joc dintr-o filă și să vă alăturați dintr-o altă filă (sau chiar dintr-un alt browser Web compatibil WebRTC) folosind ID-ul de peer.
Puteți deschide consola browserului dvs. web pentru a vedea câteva informații de depanare, deoarece în acest exemplu de aplicație, clientul PeerJS a fost configurat pentru a efectua înregistrarea în jurnalizare.
Dar nu merge pentru mine!
Există două motive majore pentru care acest joc ar putea să nu funcționeze pe computer.
Este posibil să utilizați un browser web care nu acceptă încă API-urile WebRTC necesare. Dacă acesta este cazul, poate doriți să încercați un browser diferit - unul care acceptă WebRTC și canale de date.
Dacă utilizați un browser web modern cu suport WebRTC, atunci există șansa să vă aflați în spatele unei infrastructuri de rețea pe care WebRTC nu o poate pătrunde. În mod ideal, această problemă poate fi rezolvată cu ușurință cu un server TURN, dar deoarece aplicația exemplu nu folosește unul, nu va funcționa atunci când atât tu, cât și adversarul tău sunteți în spatele NAT-urilor.
Concluzie
WebRTC este o tehnologie nouă, iar implementările sale sunt destul de departe de a fi mature. Acestea cauzează adesea unele provocări unice pentru dezvoltatori. Cu toate acestea, odată cu disponibilitatea bibliotecilor precum PeerJS, care abstrac cu grijă API-urile brute brute, tehnologia devine deja destul de accesibilă.
Sper că acest scurt tutorial pentru construirea unui joc bazat pe PeerJS vă va ajuta să începeți cu WebRTC și să construiți niște aplicații web peer-to-peer uimitoare în timp real.