Cluiche il-imreora a aistriú ó C++ chuig an ngréasán le Cheerp, WebRTC agus Firebase

Réamhrá

ár gcomhlacht Teicneolaíochtaí Leaning soláthraíonn sé réitigh chun feidhmchláir thraidisiúnta deisce a aistriú chuig an ngréasán. Ár tiomsaitheoir C++ cheerp gineann sé meascán de WebAssembly agus JavaScript, a sholáthraíonn an dá cheann idirghníomhú brabhsálaí simplí, agus ardfheidhmíocht.

Mar shampla dá chur i bhfeidhm, shocraigh muid cluiche il-imreora a phortáil chuig an ngréasán agus roghnaigh muid Teeworlds. Is cluiche retro 2D il-imreora é Teeworlds le pobal beag ach gníomhach imreoirí (mise san áireamh!). Tá sé beag i dtéarmaí acmhainní íoslódála agus riachtanais LAP agus GPU - iarrthóir idéalach.

Cluiche il-imreora a aistriú ó C++ chuig an ngréasán le Cheerp, WebRTC agus Firebase
Rith sa bhrabhsálaí Teeworlds

Shocraigh muid an tionscadal seo a úsáid chun triail a bhaint as réitigh ghinearálta chun cód líonra a aistriú chuig an ngréasán. De ghnáth déantar é seo ar na bealaí seo a leanas:

  • XMLHttpIarratas/gabháil, más rud é nach bhfuil sa chuid líonra ach iarratais HTTP, nó
  • WebSockets.

Éilíonn an dá réiteach comhpháirt freastalaí a óstáil ar thaobh an fhreastalaí, agus ní cheadaíonn an dá réiteach é a úsáid mar phrótacal iompair UDP. Tá sé seo tábhachtach le haghaidh feidhmchláir fíor-ama ar nós bogearraí agus cluichí físchomhdhála, toisc go ráthaíonn sé seachadadh agus ord paicéid prótacail TCP d'fhéadfadh sé a bheith ina bhac ar latency íseal.

Tá tríú bealach ann - úsáid an líonra ón mbrabhsálaí: WebRTC.

RTCDataCainéal Tacaíonn sé le tarchur iontaofa agus neamhiontaofa (sa chás deiridh déanann sé iarracht UDP a úsáid mar phrótacal iompair nuair is féidir), agus is féidir é a úsáid le cianfhreastalaí agus idir brabhsálaithe. Ciallaíonn sé seo gur féidir linn an feidhmchlár iomlán a phortáil chuig an mbrabhsálaí, an chomhpháirt freastalaí san áireamh!

Mar sin féin, tagann deacracht bhreise leis seo: sular féidir le beirt chomhghleacaithe WebRTC cumarsáid a dhéanamh, ní mór dóibh croitheadh ​​láimhe sách casta a dhéanamh chun nascadh, rud a éilíonn roinnt eintiteas tríú páirtí (freastalaí comharthaíochta agus freastalaí amháin nó níos mó. STUN/CAS).

Go hidéalach, ba mhaith linn API líonra a chruthú a úsáideann WebRTC go hinmheánach, ach atá chomh gar agus is féidir do chomhéadan UDP Sockets nach gá nasc a bhunú.

Ligfidh sé seo dúinn leas a bhaint as WebRTC gan a bheith orainn sonraí casta a nochtadh don chód iarratais (a bhíomar ag iarraidh a athrú chomh beag agus is féidir inár dtionscadal).

WebRTC íosta

Is sraith API é WebRTC atá ar fáil i mbrabhsálaithe a sholáthraíonn tarchur piar-le-piara sonraí fuaime, físe agus treallach.

Bunaítear an nasc idir piaraí (fiú má tá NAT ar thaobh amháin nó an dá thaobh) ag baint úsáide as freastalaithe STUN agus/nó TURN trí mheicníocht ar a dtugtar ICE. Malartaíonn piaraí faisnéis ICE agus paraiméadair cainéil trí thairiscint agus freagra an phrótacail PFS.

WOW! Cé mhéad giorrúchán ag aon am amháin? Míneoimis go hachomair cad is brí leis na téarmaí seo:

  • Fóntais Trasnaithe Seisiúin do NAT (STUN) — prótacal chun NAT a sheachaint agus péire (IP, port) a fháil chun sonraí a mhalartú go díreach leis an óstach. Má éiríonn leis a thasc a chur i gcrích, ansin is féidir le piaraí sonraí a mhalartú go neamhspleách lena chéile.
  • Trasnaigh Ag Úsáid Athsheachadáin timpeall NAT (CAS) úsáidtear é freisin do thrasnú NAT, ach cuireann sé é seo i bhfeidhm trí shonraí a chur ar aghaidh trí sheachvótálaí atá le feiceáil ag an dá phiaraí. Cuireann sé latency agus tá sé níos costasaí a chur i bhfeidhm ná STUN (toisc go gcuirtear i bhfeidhm é ar feadh an tseisiúin cumarsáide ar fad), ach uaireanta is é an t-aon rogha atá ann.
  • Bunú Nascachta Idirghníomhach (ICE) a úsáidtear chun an modh is fearr is féidir a roghnú chun dhá phiaraí a nascadh bunaithe ar fhaisnéis a fhaightear ó phiaraí a nascadh go díreach, chomh maith le faisnéis a fhaigheann líon ar bith freastalaithe STUN agus TURN.
  • Prótacal Cur Síos ar an Seisiún (PFS) formáid chun cur síos a dhéanamh ar pharaiméadair chainéil naisc, mar shampla, iarrthóirí ICE, codecs ilmheán (i gcás cainéal fuaime/físe), etc... Seolann duine de na piaraí Tairiscint PFS, agus freagraíonn an dara ceann le Freagra SDP . Tar éis seo, cruthaítear cainéal.

Chun nasc den sórt sin a chruthú, ní mór do phiaraí an fhaisnéis a fhaigheann siad ó na freastalaithe STUN agus TURN a bhailiú agus é a mhalartú lena chéile.

Is í an fhadhb atá ann ná nach bhfuil an cumas acu cumarsáid dhíreach a dhéanamh go fóill, mar sin ní mór meicníocht lasmuigh den bhanna a bheith ann chun na sonraí seo a mhalartú: freastalaí comharthaíochta.

Is féidir le freastalaí comharthaíochta a bheith an-simplí mar is é an t-aon jab atá aige ná sonraí a chur ar aghaidh idir piaraí sa chéim chroitheadh ​​láimhe (mar a thaispeántar sa léaráid thíos).

Cluiche il-imreora a aistriú ó C++ chuig an ngréasán le Cheerp, WebRTC agus Firebase
Léaráid simplithe de chroitheadh ​​láimhe WebRTC

Forbhreathnú ar Shamhail Líonra Teeworlds

Tá ailtireacht líonra Teeworlds an-simplí:

  • Is dhá chlár éagsúla iad na comhpháirteanna cliant agus freastalaí.
  • Téann cliaint isteach sa chluiche trí nascadh le ceann amháin de roinnt freastalaithe, agus ní bhíonn ach cluiche amháin ag gach ceann acu ag an am.
  • Déantar gach aistriú sonraí sa chluiche tríd an bhfreastalaí.
  • Úsáidtear máistirfhreastalaí speisialta chun liosta a bhailiú de na freastalaithe poiblí go léir a thaispeánfar sa chliant cluiche.

Buíochas le húsáid WebRTC le haghaidh malartú sonraí, is féidir linn comhpháirt freastalaí an chluiche a aistriú chuig an mbrabhsálaí ina bhfuil an cliant suite. Tugann sé seo deis iontach dúinn...

Faigh réidh le freastalaithe

Tá buntáiste deas ag an easpa loighic freastalaí: is féidir linn an feidhmchlár iomlán a imscaradh mar ábhar statach ar Leathanaigh Github nó ar ár gcuid crua-earraí féin taobh thiar de Cloudflare, rud a chinntíonn íoslódálacha tapa agus ard-am saor in aisce. Go deimhin, is féidir linn dearmad a dhéanamh orthu, agus má tá an t-ádh linn agus go dtiocfaidh an-tóir ar an gcluiche, ní bheidh gá leis an mbonneagar a nuachóiriú.

Mar sin féin, le go n-oibreoidh an córas, ní mór dúinn fós ailtireacht sheachtrach a úsáid:

  • Freastalaí STUN amháin nó níos mó: Tá roinnt roghanna saor in aisce againn le roghnú astu.
  • Freastalaí TURN amháin ar a laghad: níl aon roghanna saor in aisce anseo, ionas gur féidir linn ár gcuid féin a bhunú nó íoc as an tseirbhís. Go fortunately, an chuid is mó den am is féidir an nasc a bhunú trí fhreastalaithe STUN (agus cuir fíor-p2p ar fáil), ach tá gá le TURN mar rogha cúltaca.
  • Freastalaí Comharthaíochta: Murab ionann agus an dá ghné eile, níl an chomharthaíocht caighdeánaithe. Braitheann an méid a bheidh an freastalaí comharthaíochta freagrach as go pointe áirithe ar an bhfeidhmchlár. Is é ár gcás, sula mbunaítear nasc, is gá méid beag sonraí a mhalartú.
  • Máistirfhreastalaí Teeworlds: Úsáideann freastalaithe eile é chun a bhfuil ann a fhógairt agus úsáideann cliaint é chun freastalaithe poiblí a aimsiú. Cé nach bhfuil sé ag teastáil (is féidir le cliaint ceangal i gcónaí le freastalaí a bhfuil eolas acu air de láimh), bheadh ​​​​sé deas a bheith ann ionas gur féidir le himreoirí páirt a ghlacadh i gcluichí le daoine randamacha.

Shocraigh muid freastalaithe STUN saor in aisce Google a úsáid, agus d’imlonníomar freastalaí TURN amháin sinn féin.

Don dá phointe dheireanacha a d’úsáideamar Firebase:

  • Cuirtear máistirfhreastalaí Teeworlds i bhfeidhm go han-simplí: mar liosta de na rudaí ina bhfuil faisnéis (ainm, IP, léarscáil, modh, ...) gach freastalaí gníomhach. Foilsíonn agus nuashonraíonn freastalaithe a réad féin, agus tógann cliaint an liosta iomlán agus taispeánann sé don imreoir é. Taispeánaimid an liosta ar an leathanach baile mar HTML freisin ionas gur féidir le himreoirí cliceáil ar an bhfreastalaí agus iad a thabhairt díreach chuig an gcluiche.
  • Tá dlúthbhaint ag comharthaíocht lenár bhfeidhmiú soicéid, a gcuirtear síos air sa chéad chuid eile.

Cluiche il-imreora a aistriú ó C++ chuig an ngréasán le Cheerp, WebRTC agus Firebase
Liosta de na freastalaithe taobh istigh den chluiche agus ar an leathanach baile

Soicéid a chur i bhfeidhm

Ba mhaith linn API a chruthú atá chomh gar do Posix UDP Sockets agus is féidir chun líon na n-athruithe is gá a íoslaghdú.

Ba mhaith linn freisin an t-íosmhéid is gá a chur i bhfeidhm don mhalartú sonraí is simplí thar an líonra.

Mar shampla, ní gá dúinn fíorródú a dhéanamh: tá gach piaraí ar an "LAN fíorúil" céanna a bhaineann le cás sonrach bhunachar sonraí Firebase.

Mar sin, ní gá seoltaí IP uathúla a bheith againn: is leor eochairluachanna uathúla Firebase (cosúil le hainmneacha fearainn) chun piaraí a aithint go huathúil, agus sannann gach piaraí seoltaí IP “falsa” go háitiúil do gach eochair a chaithfear a aistriú. Cuireann sé seo deireadh go hiomlán leis an ngá atá le sannadh seoladh IP domhanda, ar tasc neamhfhánach é.

Seo an t-íosmhéid API a theastaíonn uainn a chur i bhfeidhm:

// 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);

Tá an API simplí agus cosúil leis an Posix Sockets API, ach tá roinnt difríochtaí tábhachtacha ann: aisghlaonna a logáil, IPanna áitiúla a shannadh, agus naisc leisciúla.

Aisghlaonna a Chlárú

Fiú má úsáideann an bunchlár I/O neamh-bhloic, ní mór an cód a athmhacrú chun é a rith i mbrabhsálaí gréasáin.

Is é an chúis atá leis seo ná go bhfuil lúb na hócáide sa bhrabhsálaí i bhfolach ón gclár (bíodh sé JavaScript nó WebAssembly).

Sa timpeallacht dhúchais is féidir linn cód mar seo a scríobh

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;
    ...
  }
  ...
}

Má tá lúb na hócáide i bhfolach dúinn, ní mór dúinn é a iompú ina rud mar seo:

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

Sannadh IP áitiúil

Ní seoltaí IP iad na haitheantais nód inár “líonra”, ach eochracha Firebase (is teaghráin iad a bhfuil cuma mar seo orthu: -LmEC50PYZLCiCP-vqde ).

Tá sé seo áisiúil toisc nach bhfuil meicníocht ag teastáil uainn chun IPanna a shannadh agus a n-uathúlacht a sheiceáil (chomh maith lena dhiúscairt tar éis don chliaint a bheith dícheangailte), ach is minic is gá piaraí a aithint de réir luach uimhriúil.

Is é seo go díreach cad a úsáidtear na feidhmeanna le haghaidh. resolve и reverseResolve: Faigheann an feidhmchlár ar bhealach éigin luach teaghrán na heochrach (trí ionchur úsáideora nó tríd an máistirfhreastalaí), agus is féidir é a thiontú go seoladh IP le haghaidh úsáide inmheánach. Faigheann an chuid eile den API an luach seo freisin in ionad teaghrán le haghaidh simplíochta.

Tá sé seo cosúil le cuardach DNS, ach déantar é go háitiúil ar an gcliant.

Is é sin le rá, ní féidir seoltaí IP a roinnt idir cliaint éagsúla, agus má tá gá le haitheantóir domhanda de chineál éigin, caithfear é a ghiniúint ar bhealach eile.

Ceangal leisciúil

Ní gá nasc a bheith ag UDP, ach mar atá feicthe againn, tá próiseas ceangail fada de dhíth ar WebRTC sular féidir leis tosú ag aistriú sonraí idir beirt phiaraí.

Más mian linn an leibhéal céanna astarraingthe a sholáthar, (sendto/recvfrom le piaraí treallach gan nasc roimh ré), ansin caithfidh siad nasc “leisciúil” (moill) a dhéanamh taobh istigh den API.

Seo a tharlaíonn le linn gnáthchumarsáide idir an “freastalaí” agus an “cliant” agus an UDP á úsáid, agus cad ba cheart don leabharlann againn a dhéanamh:

  • Glaonna freastalaí bind()a insint don chóras oibriúcháin go bhfuil sé ag iarraidh paicéid a fháil ar an gcalafort sonraithe.

Ina áit sin, foilseoimid port oscailte do Firebase faoin eochair fhreastalaí agus éistfimid le haghaidh imeachtaí ina fhochrann.

  • Glaonna freastalaí recvfrom(), ag glacadh le paicéid a thagann ó aon óstach ar an gcalafort seo.

Inár gcás, ní mór dúinn scuaine na bpacáistí a sheoltar chuig an gcalafort seo a sheiceáil.

Tá a scuaine féin ag gach calafort, agus cuirimid na poirt foinse agus cinn scríbe le tús na datagrams WebRTC ionas go mbeidh a fhios againn cén scuaine le cur ar aghaidh chuici nuair a thagann paicéad nua isteach.

Níl aon bhlocáil ag baint leis an nglao, mar sin mura bhfuil paicéid ann, ní dhéanaimid ach -1 a chur ar ais agus a shocrú errno=EWOULDBLOCK.

  • Faigheann an cliant IP agus calafort an fhreastalaí trí mhodhanna seachtracha áirithe, agus glaonna sendto(). Déanann sé seo glao inmheánach freisin. bind(), dá bhrí sin ina dhiaidh sin recvfrom() gheobhaidh sé an freagra gan ceangal a fhorghníomhú go sainráite.

Is é ár gcás, faigheann an cliant an eochair teaghrán go seachtrach agus úsáideann sé an fheidhm resolve() chun seoladh IP a fháil.

Ag an bpointe seo, cuirimid tús le croitheadh ​​láimhe WebRTC mura bhfuil an dá phiaraí ceangailte lena chéile fós. Úsáideann naisc le calafoirt éagsúla den phiara céanna an WebRTC DataChannel céanna.

Déanaimid feidhmiú indíreach freisin bind()ionas gur féidir leis an bhfreastalaí athcheangal sa chéad cheann eile sendto() ar eagla go ndúnfaí é ar chúis éigin.

Cuirtear nasc an chliaint ar an eolas don fhreastalaí nuair a scríobhann an cliant a thairiscint SDP faoi fhaisnéis calafoirt an fhreastalaí i Firebase, agus freagraíonn an freastalaí lena fhreagra ansin.

Taispeánann an léaráid thíos sampla de shreabhadh teachtaireachta do scéim soicéad agus tarchur na chéad teachtaireachta ón gcliant chuig an bhfreastalaí:

Cluiche il-imreora a aistriú ó C++ chuig an ngréasán le Cheerp, WebRTC agus Firebase
Léaráid iomlán den chéim nasc idir an cliant agus an freastalaí

Conclúid

Má tá sé léite agat go dtí seo, is dócha go mbeadh suim agat an teoiric a fheiceáil i ngníomh. Is féidir an cluiche a imirt ar teeworlds.leaningtech.com, bain triail as!


Cluiche cairdiúil idir comhghleacaithe

Tá cód leabharlainne an líonra ar fáil saor in aisce ag Github. Glac páirt sa chomhrá ar ár gcainéal ag Gitter!

Foinse: will.com

Add a comment