Fandefasana lalao marobe avy amin'ny C++ mankany amin'ny tranonkala miaraka amin'ny Cheerp, WebRTC ary Firebase

fampidirana

ny orinasanay Leaning Technologies manome vahaolana amin'ny fandefasana ny fampiharana desktop mahazatra amin'ny tranonkala. Ny C++ compiler cheerp miteraka fitambaran'ny WebAssembly sy JavaScript, izay manome azy roa fifandraisana navigateur tsotra, ary fampisehoana avo lenta.

Ho ohatra amin'ny fampiharana azy dia nanapa-kevitra izahay ny handefa lalao marobe amin'ny Internet ary nisafidy Teeworlds. Teeworlds dia lalao retro XNUMXD Multiplayer miaraka amina vondrom-piarahamonina mpilalao kely nefa mavitrika (anisan'izany izaho!). Kely izy io na eo amin'ny resaka loharanon-karena alaina sy ny fepetra takiana amin'ny CPU sy GPU - kandidΓ  tena tsara.

Fandefasana lalao marobe avy amin'ny C++ mankany amin'ny tranonkala miaraka amin'ny Cheerp, WebRTC ary Firebase
Mihazakazaka ao amin'ny navigateur Teeworlds

Nanapa-kevitra ny hampiasa ity tetikasa ity izahay hanandrana vahaolana ankapobeny amin'ny fandefasana kaody tambajotra amin'ny tranonkala. Izany dia atao amin'ny fomba manaraka matetika:

  • XMLHttpRequest/fetch, raha tsy misy afa-tsy fangatahana HTTP ny ampahany amin'ny tambajotra, na
  • faladia web.

Ireo vahaolana roa ireo dia mitaky fampiantranoana singa mpizara amin'ny lafiny mpizara, ary samy tsy mamela ny fampiasana ho protocole fitaterana UDP. Zava-dehibe izany ho an'ny fampiharana amin'ny fotoana tena izy toy ny rindrambaiko fihaonambe video sy lalao, satria miantoka ny fandefasana sy ny filaharan'ny fonosana protocol. TCP mety ho lasa sakana amin'ny latency ambany.

Misy fomba fahatelo - mampiasa ny tambajotra avy amin'ny navigateur: WebRTC.

RTCDataChannel Izy io dia manohana ny fifindran'ny azo antoka sy tsy azo ianteherana (amin'ity tranga farany ity dia manandrana mampiasa UDP ho protocole fitaterana izy raha azo atao), ary azo ampiasaina amin'ny mpizara lavitra sy eo anelanelan'ny navigateur. Midika izany fa afaka mandefa ny fampiharana manontolo amin'ny navigateur isika, anisan'izany ny singa mpizara!

Na izany aza, miaraka amin'ny fahasarotana fanampiny izany: alohan'ny ahafahan'ny mpizara WebRTC roa mifandray, dia mila manao fifanomezan-tanana somary saro-pady izy ireo mba hifandraisana, izay mitaky vondron'antoko fahatelo (server famantarana sy mpizara iray na maromaro. finaritra/kosa).

Ny tsara indrindra dia tianay ny mamorona API tambajotra izay mampiasa ny WebRTC anatiny, saingy akaiky araka izay azo atao amin'ny interface UDP Sockets izay tsy mila mametraka fifandraisana.

Izany dia ahafahantsika manararaotra ny WebRTC nefa tsy mila mamoaka antsipiriany be pitsiny amin'ny kaody fampiharana (izay tiantsika hovana kely araka izay azo atao amin'ny tetikasantsika).

WebRTC farafahakeliny

WebRTC dia andiana API hita amin'ny mpitety tranonkala izay manome fampitana feo, horonan-tsary ary angona tsy misy dikany.

Ny fifandraisana eo amin'ny mpiara-mianatra dia napetraka (na dia misy NAT amin'ny lafiny iray na roa) amin'ny fampiasana ny server STUN sy/na TURN amin'ny alΓ lan'ny mekanika antsoina hoe ICE. Ny mpiara-mianatra dia mifanakalo vaovao momba ny ICE sy ny mari-pamantarana fantsona amin'ny alΓ lan'ny tolotra sy valiny amin'ny protocol SDP.

Oay! Firy ny fanafohezana indray mandeha? Andeha hohazavaina fohifohy ny dikan'ireo teny ireo:

  • Session Traversal Utilities ho an'ny NAT (finaritra) β€” protocole handosirana ny NAT sy hahazoana mpivady (IP, port) mba hifanakalozana data mivantana amin'ny mpampiantrano. Raha mahavita mamita ny asany izy, dia afaka mifanakalo angona tsy miankina ny mpiara-mianatra aminy.
  • Fandalovana amin'ny fampitaovana manodidina ny NAT (kosa) dia ampiasaina amin'ny fandalovan'ny NAT ihany koa, fa mampihatra izany amin'ny alΓ lan'ny fandefasana angon-drakitra amin'ny alΓ lan'ny proxy izay hitan'ny namany roa. Manampy fahatarana izany ary lafo kokoa ny fampiharana noho ny STUN (satria ampiharina mandritra ny fotoam-pifandraisan-davitra iray manontolo), fa indraindray dia io ihany no safidy.
  • Fametrahana fifandraisana Interactive (ICE) ampiasaina mba hisafidianana ny fomba tsara indrindra azo atao amin'ny fampifandraisana namana roa mifototra amin'ny fampahalalana azo avy amin'ny fifandraisana mivantana, ary koa ny fampahalalana voarain'ny mpizara STUN sy TURN.
  • Session Description Protocol (SDP) dia endrika iray hamaritana ny mari-pamantarana fantsom-pifandraisana, ohatra, ny kandidan'ny ICE, codec multimedia (raha misy fantsona audio/video), sns... Ny iray amin'ireo namana dia mandefa tolotra SDP, ary ny faharoa dia mamaly amin'ny SDP Valiny . Aorian'izany dia misy fantsona iray noforonina.

Mba hamoronana fifandraisana toy izany dia mila manangona ny vaovao azony avy amin'ny mpizara STUN sy TURN ny mpiara-mianatra ary mifanakalo izany.

Ny olana dia tsy mbola afaka mifandray mivantana izy ireo, noho izany dia tsy maintsy misy mekanika ivelan'ny tarika mba hanakalozana ity data ity: mpizara famantarana.

Ny mpizara famantarana dia mety ho tena tsotra satria ny hany asany dia ny mandefa angon-drakitra eo amin'ny mpiara-mianatra amin'ny dingana fifampikasohana (araka ny aseho amin'ny kisary etsy ambany).

Fandefasana lalao marobe avy amin'ny C++ mankany amin'ny tranonkala miaraka amin'ny Cheerp, WebRTC ary Firebase
Diagram ny filaharan'ny fifampizarana tΓ nana WebRTC

Teeworlds Network Model Overview

Tena tsotra ny rafitry ny tambajotra Teeworlds:

  • Ny singa mpanjifa sy mpizara dia programa roa samy hafa.
  • Ny mpanjifa dia miditra amin'ny lalao amin'ny alΓ lan'ny fampifandraisana amin'ny iray amin'ireo mpizara maromaro, izay samy manana lalao iray ihany isaky ny mandeha.
  • Ny famindrana angon-drakitra rehetra amin'ny lalao dia atao amin'ny alΓ lan'ny mpizara.
  • Ny mpizara master manokana dia ampiasaina hanangonana ny lisitry ny mpizara ho an'ny daholobe rehetra izay aseho amin'ny mpanjifa lalao.

Noho ny fampiasana ny WebRTC amin'ny fifanakalozana angona, dia afaka mamindra ny singa mpizara amin'ny lalao amin'ny navigateur misy ny mpanjifa. Izany dia manome antsika fahafahana lehibe ...

Esory ny mpizara

Ny tsy fahampian'ny lojika mpizara dia manana tombony tsara: afaka mametraka ny rindranasa manontolo ho votoaty static ao amin'ny Github Pages na amin'ny fitaovantsika manokana ao ambadiky ny Cloudflare isika, ka miantoka ny fampidinana haingana sy ny fotoana ambony maimaim-poana. Raha ny marina dia afaka manadino azy ireo isika, ary raha tsara vintana isika ary lasa malaza ny lalao, dia tsy voatery havaozina ny fotodrafitrasa.

Na izany aza, raha te hiasa ny rafitra dia mbola mila mampiasa maritrano ivelany isika:

  • Mpizara STUN iray na maromaro: Manana safidy malalaka maro azo isafidianana izahay.
  • Mpizara TURN iray farafahakeliny: tsy misy safidy maimaim-poana eto, ka afaka manangana ny anay izahay na mandoa ny serivisy. Soa ihany fa ny ankamaroan'ny fotoana dia azo apetraka amin'ny alΓ lan'ny mpizara STUN ny fifandraisana (ary manome p2p marina), fa ny TURN dia ilaina ho safidy miverina.
  • Mpizara famantarana: Tsy mitovy amin'ireo lafiny roa hafa, ny famantarana dia tsy manara-penitra. Ny tena tompon'andraikitra amin'ny mpizara famantarana dia miankina amin'ny fampiharana. Amin'ny tranga misy antsika, alohan'ny hametrahana fifandraisana dia ilaina ny manakalo data kely.
  • Teeworlds Master Server: Ampiasain'ny mpizara hafa izy io mba hanambarana ny fisiany sy ny mpanjifa mba hitadiavana mpizara ho an'ny daholobe. Na dia tsy takiana aza izany (afaka mifandray amin'ny lohamilina fantany amin'ny tanana foana ny mpanjifa), dia tsara ny manana izany mba ahafahan'ny mpilalao mandray anjara amin'ny lalao miaraka amin'ny olona tsy misy dikany.

Nanapa-kevitra ny hampiasa ny mpizara STUN maimaimpoana an'ny Google izahay, ary nametraka mpizara TURN iray ny tenanay.

Ho an'ireo teboka roa farany dia nampiasainay Firebase:

  • Ny mpizara master Teeworlds dia ampiharina amin'ny fomba tsotra: toy ny lisitry ny zavatra misy fampahalalana (anarana, IP, sarintany, fomba, ...) an'ny mpizara mavitrika tsirairay. Mamoaka sy manavao ny zavatra ilain'izy ireo ny mpizara, ary ny mpanjifa dia mandray ny lisitra manontolo ary mampiseho izany amin'ny mpilalao. Asehonay ihany koa ny lisitra ao amin'ny pejy fandraisana ho HTML mba ahafahan'ny mpilalao manindry fotsiny ny lohamilina ary entina mivantana amin'ny lalao.
  • Ny fampandrenesana dia mifandray akaiky amin'ny fampiharana ny faladiantsika, voalaza ao amin'ny fizarana manaraka.

Fandefasana lalao marobe avy amin'ny C++ mankany amin'ny tranonkala miaraka amin'ny Cheerp, WebRTC ary Firebase
Lisitry ny mpizara ao anatin'ny lalao sy ao amin'ny pejy fandraisana

Fampiharana ny sockets

Tianay ny hamorona API izay akaiky ny Posix UDP Sockets mba hampihenana ny isan'ny fanovana ilaina.

Tianay ihany koa ny hampihatra ny kely indrindra ilaina amin'ny fifanakalozana angona tsotra indrindra amin'ny tambajotra.

Ohatra, tsy mila lalana tena izy isika: mitovy amin'ny "LAN virtoaly" mifandray amin'ny ohatra angon-drakitra Firebase manokana ny namana rehetra.

Noho izany, tsy mila adiresy IP tokana izahay: ny soatoavina fototra Firebase tokana (mitovitovy amin'ny anaran'ny sehatra) dia ampy hamantarana ny mitovy aminy, ary ny mpiara-mianatra tsirairay dia manome adiresy IP "soka" ho an'ny fanalahidy tsirairay mila adika. Izany dia manafoana tanteraka ny filana ny adiresy IP manerantany, izay asa tsy misy dikany.

Ity ny API ambany indrindra tokony hampiharina:

// Create and destroy a socket
int socket();
int close(int fd);
// Bind a socket to a port, and publish it on Firebase
int bind(int fd, AddrInfo* addr);
// Send a packet. This lazily create a WebRTC connection to the 
// peer when necessary
int sendto(int fd, uint8_t* buf, int len, const AddrInfo* addr);
// Receive the packets destined to this socket
int recvfrom(int fd, uint8_t* buf, int len, AddrInfo* addr);
// Be notified when new packets arrived
int recvCallback(Callback cb);
// Obtain a local ip address for this peer key
uint32_t resolve(client::String* key);
// Get the peer key for this ip
String* reverseResolve(uint32_t addr);
// Get the local peer key
String* local_key();
// Initialize the library with the given Firebase database and 
// WebRTc connection options
void init(client::FirebaseConfig* fb, client::RTCConfiguration* ice);

Ny API dia tsotra ary mitovy amin'ny Posix Sockets API, saingy misy fahasamihafana lehibe vitsivitsy: logging callbacks, manendry IP eo an-toerana, ary malaina fifandraisana.

Misoratra anarana Callbacks

Na dia mampiasa I/O tsy manakana aza ny programa tany am-boalohany, dia tsy maintsy averina averina ny kaody mba handehanana amin'ny navigateur web.

Ny anton'izany dia ny fikandrana hetsika ao amin'ny navigateur dia miafina amin'ny programa (na JavaScript na WebAssembly).

Ao amin'ny tontolo teratany dia afaka manoratra code toy izao isika

while(running) {
  select(...); // wait for I/O events
  while(true) {
    int r = readfrom(...); // try to read
    if (r < 0 && errno == EWOULDBLOCK) // no more data available
      break;
    ...
  }
  ...
}

Raha miafina amintsika ny loop hetsika, dia mila mamadika azy ho toy izao isika:

auto cb = []() { // this will be called when new data is available
  while(true) {
    int r = readfrom(...); // try to read
    if (r < 0 && errno == EWOULDBLOCK) // no more data available
      break;
    ...
  }
  ...
};
recvCallback(cb); // register the callback

Fanendrena IP eo an-toerana

Ny ID node ao amin'ny "tambajotra" dia tsy adiresy IP, fa fanalahidy Firebase (tady toy izao izy ireo: -LmEC50PYZLCiCP-vqde ).

Mety izany satria tsy mila mekanika hanendry IP sy hijerena ny maha-tokana azy isika (ary koa ny fanariana azy ireo rehefa tapaka ny fifandraisan'ny mpanjifa), fa matetika dia ilaina ny mamantatra ny namany amin'ny sanda isa.

Izany indrindra no ampiasaina amin'ny asa. resolve ΠΈ reverseResolve: Ny fampiharana dia mahazo ny sandan'ny kofehy amin'ny lakile (amin'ny alΓ lan'ny fampidirana mpampiasa na amin'ny alΓ lan'ny server master), ary afaka manova izany ho adiresy IP ho an'ny fampiasana anatiny. Ny ambiny amin'ny API koa dia mahazo io sanda io fa tsy tady ho an'ny fahatsorana.

Mitovy amin'ny fitadiavana DNS izany, fa natao teo an-toerana tamin'ny mpanjifa.

Izany hoe, ny adiresy IP dia tsy azo zaraina amin'ny mpanjifa samihafa, ary raha ilaina ny karazana famantarana manerantany dia tsy maintsy mamorona amin'ny fomba hafa.

Fifandraisana kamo

Tsy mila fifandraisana ny UDP, fa araka ny efa hitantsika, ny WebRTC dia mitaky dingana fampifandraisana lava alohan'ny ahafahany manomboka mamindra angona eo amin'ny namana roa.

Raha te-hanome ny haavon'ny abstraction mitovy isika, (sendto/recvfrom miaraka amin'ny mpiara-mianatra tsy misy ifandraisany tsy misy fifandraisana aloha), dia tsy maintsy manao fifandraisana "kamo" izy ireo ao anatin'ny API.

Izany no mitranga mandritra ny fifandraisana mahazatra eo amin'ny "server" sy ny "client" rehefa mampiasa UDP, ary inona no tokony hataon'ny tranomboky:

  • Miantso ny mpizara bind()mba hilazana amin'ny rafitra miasa fa te-handray fonosana amin'ny seranana voatondro.

Fa kosa, hamoaka seranan-tsambo misokatra ho an'ny Firebase eo ambanin'ny fanalahidin'ny mpizara izahay ary hihaino ny hetsika ao amin'ny zana-kazony.

  • Miantso ny mpizara recvfrom(), manaiky fonosana avy amin'ny mpampiantrano rehetra amin'ity seranana ity.

Amin'ny tranga misy antsika dia mila manamarina ny filaharana miditra amin'ny fonosana alefa amin'ity seranana ity.

Ny seranan-tsambo tsirairay dia manana filaharana manokana, ary ampianay ny loharano sy ny seranan-tsambo ho any amin'ny fiandohan'ny datagrams WebRTC mba hahafantarantsika izay filaharana halefa rehefa tonga ny fonosana vaovao.

Ny antso dia tsy fanakanana, ka raha tsy misy fonosana dia averinay fotsiny -1 ary apetraka errno=EWOULDBLOCK.

  • Ny mpanjifa dia mandray ny IP sy ny seranan-tsambon'ny mpizara amin'ny fomba ivelany sasany, ary miantso sendto(). Izany koa dia manao antso anatiny. bind(), noho izany manaraka izany recvfrom() dia hahazo ny valin-teny nefa tsy manatanteraka mazava ny bid.

Amin'ny tranga misy antsika, ny mpanjifa dia mandray ny fanalahidin'ny string ary mampiasa ny fiasa resolve() mba hahazoana adiresy IP.

Amin'izao fotoana izao dia manomboka fifampikasihan-tanana amin'ny WebRTC isika raha mbola tsy mifandray ny mpiara-mianatra roa. Ny fifandraisana amin'ny seranana samy hafa mitovy amin'ny mitovy dia mampiasa WebRTC DataChannel mitovy.

Manao ankolaka koa izahay bind()mba hahafahan'ny mpizara mifandray indray amin'ny manaraka sendto() raha sanatria nakatona noho ny antony.

Ampandrenesina momba ny fifandraisan'ny mpanjifa ny mpizara rehefa manoratra ny tolotra SDP-ny eo ambanin'ny fampahafantarana momba ny seranan-tsambo ao amin'ny Firebase ny mpizara, ary mamaly miaraka amin'ny valin-teniny ao ny mpizara.

Ny kisary etsy ambany dia mampiseho ohatra iray momba ny fikorianan'ny hafatra ho an'ny rafitra socket sy ny fandefasana ny hafatra voalohany avy amin'ny mpanjifa mankany amin'ny mpizara:

Fandefasana lalao marobe avy amin'ny C++ mankany amin'ny tranonkala miaraka amin'ny Cheerp, WebRTC ary Firebase
Diagram feno momba ny dingana fampifandraisana eo amin'ny mpanjifa sy ny mpizara

famaranana

Raha namaky hatramin'izao ianao dia mety ho liana amin'ny fijerena ilay teoria miasa. Ny lalao dia azo atao amin'ny teeworlds.leaningtech.com, Andramo io!


Fifaninanam-pirahalahiana eo amin'ny mpiara-miasa

Ny kaody tranomboky tambajotra dia azo alaina maimaim-poana amin'ny Github. Midira amin'ny resaka ao amin'ny fantsonay amin'ny Gitter!

Source: www.habr.com

Add a comment