Zazzage wasan ƴan wasa da yawa daga C++ zuwa gidan yanar gizo tare da Cheerp, WebRTC da Firebase

Gabatarwar

kamfaninmu Leaning Fasaha yana ba da mafita don jigilar aikace-aikacen tebur na gargajiya zuwa gidan yanar gizo. Mai haɗa C++ na mu fara'a yana haifar da haɗin yanar gizo na WebAssembly da JavaScript, wanda ke ba da duka m browser hulda, da babban aiki.

A matsayin misali na aikace-aikacen sa, mun yanke shawarar tura wasan da yawa zuwa gidan yanar gizo kuma muka zaɓi Yananan. Teeworlds wasa ne na retro XNUMXD da yawa tare da ƙaramin yanki amma masu aiki (ciki har da ni!). Yana da ƙananan duka dangane da albarkatun da aka zazzage da buƙatun CPU da GPU - ɗan takarar da ya dace.

Zazzage wasan ƴan wasa da yawa daga C++ zuwa gidan yanar gizo tare da Cheerp, WebRTC da Firebase
Gudu a cikin Teeworlds browser

Mun yanke shawarar amfani da wannan aikin don gwaji da shi mafita na gabaɗaya don aika lambar hanyar sadarwa zuwa gidan yanar gizo. Ana yin hakan ta hanyoyi kamar haka:

  • Neman XMLHttp/kawo, idan sashin cibiyar sadarwa ya ƙunshi buƙatun HTTP kawai, ko
  • shafukan yanar gizo.

Dukansu mafita suna buƙatar ɗaukar nauyin sashin uwar garke a gefen uwar garken, kuma baya ba da izinin amfani azaman yarjejeniya ta sufuri UDP. Wannan yana da mahimmanci ga aikace-aikacen lokaci-lokaci kamar software na taron bidiyo da wasanni, saboda yana ba da garantin bayarwa da oda na fakitin yarjejeniya. TCP na iya zama cikas ga ƙarancin latency.

Akwai hanya ta uku - yi amfani da hanyar sadarwa daga mai bincike: WebRTC.

RTCDataChannel Yana goyan bayan watsa abin dogaro da abin dogaro (a cikin yanayin ƙarshe yana ƙoƙarin yin amfani da UDP azaman tsarin sufuri a duk lokacin da zai yiwu), kuma ana iya amfani dashi duka tare da uwar garken nesa da tsakanin masu bincike. Wannan yana nufin cewa za mu iya tura dukkan aikace-aikacen zuwa mai binciken, gami da bangaren uwar garken!

Koyaya, wannan yana zuwa tare da ƙarin wahala: kafin abokan aikin WebRTC guda biyu su iya sadarwa, suna buƙatar yin musafaha mai rikitarwa don haɗawa, wanda ke buƙatar ƙungiyoyin ɓangare na uku da yawa (sabar sabar sigina da sabar ɗaya ko fiye). STUN/Juya).

Da kyau, muna so mu ƙirƙiri API na cibiyar sadarwa wanda ke amfani da WebRTC a ciki, amma yana kusa da yuwuwar UDP Sockets interface wanda baya buƙatar kafa haɗin gwiwa.

Wannan zai ba mu damar yin amfani da WebRTC ba tare da bayyana hadaddun bayanai ga lambar aikace-aikacen ba (wanda muke so mu canza kadan kamar yadda zai yiwu a cikin aikinmu).

Mafi ƙarancin WebRTC

WebRTC saitin APIs ne da ake samu a cikin masu bincike waɗanda ke ba da watsawa-tsara-zuwa-tsara na sauti, bidiyo da bayanan sabani.

An kafa haɗin tsakanin takwarorinsu (ko da akwai NAT a ɗaya ko biyu) ta amfani da STUN da / ko TURN sabobin ta hanyar da ake kira ICE. Takwarorinsu suna musayar bayanan ICE da sigogin tashoshi ta hanyar tayin da amsar ka'idar SDP.

Kai! Gajarta nawa a lokaci guda? Bari mu ɗan yi bayanin abin da waɗannan sharuɗɗan ke nufi:

  • Zama Traversal Utilities for NAT (STUN) - yarjejeniya don ƙetare NAT da samun nau'i biyu (IP, tashar jiragen ruwa) don musayar bayanai kai tsaye tare da mai watsa shiri. Idan ya sami damar kammala aikinsa, to, takwarorinsu na iya yin musayar bayanai da kansu da kansu.
  • Tafiya Amfani da Relays a kusa da NAT (Juya) Hakanan ana amfani da shi don zirga-zirgar NAT, amma yana aiwatar da hakan ta hanyar tura bayanai ta hanyar wakili wanda ke bayyane ga takwarorinsu biyu. Yana ƙara latency kuma ya fi tsada don aiwatarwa fiye da STUN (saboda ana amfani dashi a duk tsawon lokacin sadarwar), amma wani lokacin shine kawai zaɓi.
  • Kafa Haɗin Haɗin Kai (ICE) ana amfani da su don zaɓar mafi kyawun hanyar haɗa takwarorinsu biyu dangane da bayanan da aka samu daga haɗa takwarorinsu kai tsaye, da kuma bayanan da aka karɓa ta kowane adadin sabobin STUN da TURN.
  • Ka'idar Bayanin Zama (SDP) tsari ne don kwatanta sigogin tashar haɗin gwiwa, alal misali, 'yan takarar ICE, codecs multimedia (a cikin yanayin tashar sauti / bidiyo), da dai sauransu ... Ɗaya daga cikin abokan aiki ya aika da tayin SDP, kuma na biyu ya amsa tare da Amsa SDP . Bayan wannan, an ƙirƙiri tasha.

Don ƙirƙirar irin wannan haɗin, takwarorinsu suna buƙatar tattara bayanan da suka karɓa daga sabobin STUN da TURN kuma su musanya shi da juna.

Matsalar ita ce har yanzu ba su da ikon sadarwa kai tsaye, don haka dole ne wata hanyar da ba ta da amfani ta kasance don musanya wannan bayanan: uwar garken sigina.

Uwar garken sigina na iya zama mai sauqi qwarai saboda kawai aikinta shine tura bayanai tsakanin takwarorinsu a lokacin musafaha (kamar yadda aka nuna a hoton da ke ƙasa).

Zazzage wasan ƴan wasa da yawa daga C++ zuwa gidan yanar gizo tare da Cheerp, WebRTC da Firebase
Siffar jeri na musafaha WebRTC mai Sauƙaƙe

Teeworlds Network Model Overview

Gine-ginen cibiyar sadarwar Teeworlds abu ne mai sauqi:

  • Abokin ciniki da sassan uwar garken shirye-shirye ne daban-daban guda biyu.
  • Abokan ciniki suna shiga wasan ta hanyar haɗawa zuwa ɗaya daga cikin sabar da yawa, kowannensu yana ɗaukar wasa ɗaya kawai a lokaci ɗaya.
  • Duk canja wurin bayanai a cikin wasan ana aiwatar da su ta uwar garken.
  • Ana amfani da uwar garken na musamman don tattara jerin duk sabar jama'a waɗanda aka nuna a cikin abokin cinikin wasan.

Godiya ga yin amfani da WebRTC don musayar bayanai, za mu iya canja wurin sashin uwar garken wasan zuwa mai binciken inda abokin ciniki yake. Wannan yana ba mu dama mai girma ...

Cire sabobin

Rashin dabaru na uwar garken yana da fa'ida mai kyau: za mu iya tura duk aikace-aikacen azaman abun ciki na tsaye akan Shafukan Github ko akan kayan aikin mu a bayan Cloudflare, don haka tabbatar da zazzagewa cikin sauri da babban lokacin kyauta. A gaskiya muna iya mantawa da su, kuma idan muka yi sa'a kuma wasan ya zama sananne, to ba dole ba ne a inganta abubuwan more rayuwa.

Koyaya, don tsarin yayi aiki, har yanzu dole ne mu yi amfani da gine-ginen waje:

  • Sabar STUN ɗaya ko fiye: Muna da zaɓuɓɓukan kyauta da yawa don zaɓar daga.
  • Aƙalla uwar garken JUYA ɗaya: babu zaɓuɓɓukan kyauta anan, saboda haka zamu iya saita namu ko biyan kuɗin sabis ɗin. Abin farin ciki, yawancin lokaci ana iya kafa haɗin haɗin ta hanyar sabobin STUN (kuma suna samar da p2p na gaskiya), amma ana buƙatar TURN a matsayin zaɓi na baya.
  • Sabar Sigina: Ba kamar sauran bangarorin biyu ba, ba a daidaita sigina ba. Abin da uwar garken sigina za ta kasance alhakinsa ya dogara da ɗan kan aikace-aikacen. A cikin yanayinmu, kafin kafa haɗin gwiwa, ya zama dole don musanya ƙaramin adadin bayanai.
  • Teeworlds Master Server: Wasu sabobin ke amfani da shi don tallata wanzuwar su da kuma abokan ciniki don nemo sabar jama'a. Duk da yake ba a buƙata ba (abokan ciniki koyaushe suna iya haɗawa da sabar da suka sani da hannu), zai yi kyau a samu don 'yan wasa su shiga cikin wasanni tare da mutane bazuwar.

Mun yanke shawarar amfani da sabobin STUN na kyauta na Google, kuma mun tura sabar TURN guda ɗaya da kanmu.

Domin maki biyu na ƙarshe da muka yi amfani da su Firebase:

  • Ana aiwatar da babban uwar garken Teeworlds a sauƙaƙe: azaman jerin abubuwan da ke ɗauke da bayanai (suna, IP, taswira, yanayin, ...) na kowane sabar mai aiki. Sabar suna bugawa da sabunta abubuwan nasu, kuma abokan ciniki suna ɗaukar jerin duka kuma su nuna shi ga mai kunnawa. Muna kuma nuna jerin akan shafin gida azaman HTML don haka 'yan wasa za su iya danna sabar kawai kuma a kai su kai tsaye zuwa wasan.
  • Sigina yana da alaƙa da aiwatar da kwas ɗin mu, wanda aka kwatanta a sashe na gaba.

Zazzage wasan ƴan wasa da yawa daga C++ zuwa gidan yanar gizo tare da Cheerp, WebRTC da Firebase
Jerin sabobin a cikin wasan da kan shafin gida

Aiwatar da kwasfa

Muna son ƙirƙirar API wanda ke kusa da Posix UDP Sockets kamar yadda zai yiwu don rage yawan canje-canjen da ake buƙata.

Muna kuma son aiwatar da mafi ƙarancin buƙata don musayar bayanai mafi sauƙi akan hanyar sadarwa.

Alal misali, ba ma buƙatar hanya ta gaske: duk takwarorinsu suna kan "LAN kama-da-wane" iri ɗaya da ke da alaƙa da takamaiman misali na bayanai na Firebase.

Saboda haka, ba ma buƙatar adiresoshin IP na musamman: maɓalli na musamman na Firebase (mai kama da sunayen yanki) sun isa su keɓance takwarorinsu, kuma kowane ɗan'uwa a cikin gida yana sanya adiresoshin IP na "ƙarya" ga kowane maɓalli da ke buƙatar fassara. Wannan gaba ɗaya yana kawar da buƙatar aikin adireshin IP na duniya, wanda ba karamin aiki bane.

Anan shine mafi ƙarancin API da muke buƙatar aiwatarwa:

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

API ɗin mai sauƙi ne kuma yayi kama da Posix Sockets API, amma yana da ƴan bambance-bambance masu mahimmanci: shigar da sake kiran waya, sanya IPs na gida, da haɗin kai na kasala.

Rijista Kiran Kira

Ko da ainihin shirin yana amfani da I/O ba tare da toshewa ba, dole ne a sake fasalin lambar don yin aiki a cikin burauzar gidan yanar gizo.

Dalilin haka shi ne cewa madauki na taron a cikin mai binciken yana ɓoye daga shirin (wasu JavaScript ko WebAssembly).

A cikin mahalli na asali za mu iya rubuta lamba kamar haka

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

Idan madauki na taron ya ɓoye mana, to muna buƙatar juya shi zuwa wani abu kamar haka:

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

Ayyukan IP na gida

ID ɗin node a cikin "cibiyar sadarwarmu" ba adiresoshin IP ba ne, amma maɓallan Firebase (su ne kirtani masu kama da wannan: -LmEC50PYZLCiCP-vqde ).

Wannan ya dace saboda ba ma buƙatar tsarin sanya IPs da bincika keɓancewarsu (da kuma zubar da su bayan abokin ciniki ya cire haɗin), amma sau da yawa ya zama dole a gano takwarorinsu ta ƙimar lamba.

Wannan shine ainihin abin da ake amfani da ayyukan. resolve и reverseResolve: Aikace-aikacen ko ta yaya yana karɓar ƙimar kirtani na maɓalli (ta hanyar shigar da mai amfani ko ta uwar garken uwar garken), kuma yana iya canza shi zuwa adireshin IP don amfani na ciki. Sauran API ɗin kuma yana karɓar wannan ƙimar maimakon kirtani don sauƙi.

Wannan yayi kama da binciken DNS, amma ana yin shi a gida akan abokin ciniki.

Wato, ba za a iya raba adiresoshin IP tsakanin abokan ciniki daban-daban ba, kuma idan ana buƙatar wani nau'in ganowa na duniya, dole ne a samar da shi ta wata hanya dabam.

Lazazzabo haɗi

UDP baya buƙatar haɗi, amma kamar yadda muka gani, WebRTC yana buƙatar tsarin haɗin gwiwa mai tsawo kafin ya fara canja wurin bayanai tsakanin takwarorinsu biyu.

Idan muna so mu samar da wannan matakin na abstraction, (sendto/recvfrom tare da takwarorinsu na sabani ba tare da haɗin kai ba), to dole ne su yi haɗin "lalalaci" (jinkirta) a cikin API.

Wannan shine abin da ke faruwa yayin sadarwa ta al'ada tsakanin "uwar garken" da "abokin ciniki" lokacin amfani da UDP, da abin da ɗakin karatu ya kamata ya yi:

  • Kiran uwar garken bind()don gaya wa tsarin aiki cewa yana son karɓar fakiti akan tashar da aka ƙayyade.

Madadin haka, za mu buga buɗaɗɗen tashar jiragen ruwa zuwa Firebase a ƙarƙashin maɓallin uwar garke kuma mu saurari abubuwan da ke faruwa a cikin ƙaramin bishiyar sa.

  • Kiran uwar garken recvfrom(), karbar fakitin da ke fitowa daga kowane mai masaukin baki a wannan tashar jiragen ruwa.

A cikin yanayinmu, muna buƙatar bincika jerin fakiti masu shigowa da aka aika zuwa wannan tashar jiragen ruwa.

Kowace tashar jiragen ruwa tana da jerin gwanonta, kuma muna ƙara tushen tushe da tashar jiragen ruwa zuwa farkon bayanan WebRTC don mu san layin da za mu tura lokacin da sabon fakiti ya zo.

Kiran baya toshewa, don haka idan babu fakiti kawai mu dawo -1 mu saita errno=EWOULDBLOCK.

  • Abokin ciniki yana karɓar IP da tashar jiragen ruwa na uwar garke ta wasu hanyoyin waje, da kira sendto(). Wannan kuma yana yin kira na ciki. bind(), don haka na gaba recvfrom() zai karɓi amsa ba tare da aiwatar da ɗaurin kai tsaye ba.

A cikin yanayinmu, abokin ciniki a waje yana karɓar maɓallin kirtani kuma yana amfani da aikin resolve() don samun adireshin IP.

A wannan gaba, muna fara musafaha na WebRTC idan har yanzu takwarorinsu biyu ba su da alaƙa da juna. Haɗin kai zuwa mabambantan tashar jiragen ruwa na takwarorinsu ɗaya suna amfani da WebRTC DataChannel iri ɗaya.

Muna kuma yin a kaikaice bind()ta yadda uwar garken zai iya sake haɗawa a gaba sendto() idan ya rufe saboda wasu dalilai.

Ana sanar da uwar garken game da haɗin abokin ciniki lokacin da abokin ciniki ya rubuta tayin ta SDP a ƙarƙashin bayanin tashar tashar uwar garken a cikin Firebase, kuma uwar garken yana amsawa tare da amsawa a can.

Hoton da ke ƙasa yana nuna misalin kwararar saƙo don makircin soket da watsa saƙon farko daga abokin ciniki zuwa uwar garken:

Zazzage wasan ƴan wasa da yawa daga C++ zuwa gidan yanar gizo tare da Cheerp, WebRTC da Firebase
Cikakken zane na lokacin haɗin kai tsakanin abokin ciniki da uwar garken

ƙarshe

Idan kun karanta wannan zuwa yanzu, tabbas kuna sha'awar ganin ka'idar tana aiki. Ana iya kunna wasan akan teeworlds.leaningtech.com, gwada shi!


Wasan sada zumunci tsakanin abokan aiki

Ana samun lambar ɗakin karatu na cibiyar sadarwa kyauta a Github. Kasance tare da tattaunawar a tasharmu a Gitter!

source: www.habr.com

Add a comment