Oer it netwurkmodel yn spultsjes foar begjinners

Oer it netwurkmodel yn spultsjes foar begjinners
De lêste twa wiken haw ik wurke oan 'e netwurkmotor foar myn spultsje. Dêrfoar wist ik hielendal neat oer netwurkjen yn spultsjes, dus ik lies in protte artikels en die in protte eksperiminten om alle begripen te begripen en myn eigen netwurkmotor te skriuwen.

Yn dizze hantlieding wol ik de ferskate begripen mei jo diele dy't jo moatte leare foardat jo jo eigen spielmotor skriuwe, lykas ek de bêste boarnen en artikels om se te learen.

Yn 't algemien binne d'r twa haadtypen fan netwurkarsjitektueren: peer-to-peer en client-server. Yn in peer-to-peer (p2p) arsjitektuer wurde gegevens oerdroegen tusken elk pear ferbûne spilers, wylst yn in client-server-arsjitektuer gegevens allinich oerdroegen wurde tusken de spilers en de tsjinner.

Hoewol't de peer-to-peer-arsjitektuer noch brûkt wurdt yn guon spultsjes, is client-tsjinner de standert: it is makliker te ymplementearjen, fereasket in lytsere kanaalbreedte en makket it makliker om te beskermjen tsjin cheat. Dêrom sille wy yn dizze hantlieding rjochtsje op 'e client-server-arsjitektuer.

Benammen binne wy ​​it meast ynteressearre yn autoritêre tsjinners: yn sokke systemen hat de tsjinner altyd gelyk. Bygelyks, as de spiler tinkt dat hy op (10, 5) is en de tsjinner fertelt him dat hy op (5, 3) is, dan moat de kliïnt syn posysje ferfange troch dejinge dy't de tsjinner rapportearret, net oarsom. It brûken fan autoritative tsjinners makket it makliker te werkennen cheaters.

D'r binne trije haadkomponinten yn gamingnetwurksystemen:

  • Ferfierprotokol: hoe't gegevens oerdroegen wurde tusken kliïnten en de tsjinner.
  • Applikaasjeprotokol: wat wurdt oerdroegen fan kliïnten nei de tsjinner en fan 'e tsjinner nei kliïnten, en yn hokker formaat.
  • Applikaasjelogika: hoe't de oerdroegen gegevens wurde brûkt om de steat fan kliïnten en de tsjinner te aktualisearjen.

It is heul wichtich om de rol fan elk diel te begripen en de swierrichheden dy't dêrmei ferbûn binne.

Ferfier protokol

De earste stap is om in protokol te kiezen foar it ferfieren fan gegevens tusken de tsjinner en kliïnten. D'r binne twa ynternetprotokollen foar dit: TCP и UDP. Mar jo kinne jo eigen ferfierprotokol oanmeitsje op basis fan ien fan har of in bibleteek brûke dy't se brûkt.

Fergeliking fan TCP en UDP

Sawol TCP as UDP binne basearre op IP. IP lit in pakket oerstjoere fan in boarne nei in ûntfanger, mar it garandearret net dat it ferstjoerde pakket de ûntfanger ier of letter sil berikke, dat it der op syn minst ien kear by komt, en dat de folchoarder fan pakketten yn komt de juste folchoarder. Boppedat kin in pakket allinich in beheinde gegevensgrutte befetsje, jûn troch de wearde MTU.

UDP is gewoan in tinne laach boppe op IP. Dêrom hat it deselde beheiningen. Yn tsjinstelling, TCP hat in protte funksjes. It leveret in betroubere oardere ferbining tusken twa knopen mei flaterkontrôle. Dêrom, TCP is hiel handich en wurdt brûkt yn in protte oare protokollen, bygelyks, yn HTTP, FTP и SMTP. Mar al dizze funksjes komme foar in priis: fertraging.

Om te begripen wêrom't dizze funksjes latency kinne feroarsaakje, moatte wy begripe hoe't TCP wurket. As de stjoerende host in pakket ferstjoert nei de ûntfangende host, ferwachtet er in erkenning (ACK) te ûntfangen. As it nei in bepaalde tiid it net ûntfangt (omdat it pakket of befêstiging ferlern gien is, of om ien of oare reden), dan stjoert it it pakket wer. Boppedat garandearret TCP dat pakketten yn 'e juste folchoarder ûntfongen wurde, dus oant in ferlern pakket wurdt ûntfongen, kinne alle oare pakketten net ferwurke wurde, sels as se al ûntfongen binne troch it ûntfangende knooppunt.

Mar sa't jo wierskynlik begripe, is latency yn multiplayer-spultsjes heul wichtich, foaral yn sokke aktive sjenres as FPS. Dêrom brûke in protte spultsjes UDP mei in eigen protokol.

In lânseigen protokol basearre op UDP kin om ferskate redenen effisjinter wêze dan TCP. It kin bygelyks guon pakketten markearje as fertroud en oaren as net fertroud. Dêrom kin it him net skele as it ûnbetroubere pakket de ûntfanger berikt hat. Of it kin meardere gegevensstreamen ferwurkje, sadat in pakket ferlern yn ien stream oare streamen net fertrage. D'r kin bygelyks in thread wêze foar ynfier fan spilers en in oare thread foar petearberjochten. As in petearberjocht dat net urgent gegevens is ferlern, dan sil it de ynfier dy't urgent is net fertrage. Of in proprietêr protokol kin betrouberens oars ymplementearje as TCP om effisjinter te wêzen yn in fideospultsjeomjouwing.

Dus, as TCP sûget, dan sille wy ús eigen ferfierprotokol bouwe basearre op UDP?

Alles is in bytsje yngewikkelder. Ek al is TCP hast sub-optimaal foar gaming netwurk systemen, it kin wurkje hiel goed foar jo spesifike spultsje en besparje jo weardefolle tiid. Wachttiid kin bygelyks gjin probleem wêze foar in turn-basearre spultsje of in spultsje dat allinich kin wurde spile op LAN-netwurken, wêr't latency en pakketferlies folle minder binne as op it ynternet.

In protte súksesfolle spultsjes, ynklusyf World of Warcraft, Minecraft, en Terraria, brûke TCP. De measte FPS's brûke lykwols har eigen UDP-basearre protokollen, dus wy sille hjirûnder mear oer har prate.

As jo ​​​​kieze om TCP te brûken, soargje dan derfoar dat it is útskeakele Nagle's algoritme, om't it pakketten buffert foar it ferstjoeren, wat betsjut dat it de fertraging fergruttet.

Om mear te learen oer de ferskillen tusken UDP en TCP yn 'e kontekst fan multiplayer-spultsjes, sjoch Glenn Fiedler's artikel UDP vs. TCP.

Eigen protokol

Dat jo wolle jo eigen ferfierprotokol oanmeitsje, mar wite net wêr't jo moatte begjinne? Jo hawwe gelok, om't Glenn Fiedler der twa geweldige artikels oer skreau. Jo sille in protte tûke ideeën yn har fine.

Earste artikel Netwurk foar spultsje programmeurs 2008, makliker as de twadde Bouwe in Game Network Protokol 2016. Ik riede oan dat jo begjinne mei de âldere.

Wês bewust dat Glenn Fiedler in grut foarstanner is fan it brûken fan jo eigen protokol basearre op UDP. En nei it lêzen fan syn artikels sille jo wierskynlik syn miening oannimme dat TCP serieuze neidielen hat yn fideospultsjes, en jo wolle jo eigen protokol ymplementearje.

Mar as jo nij binne yn netwurken, doch josels in geunst en brûk TCP as in bibleteek. Om jo eigen ferfierprotokol mei súkses út te fieren, moatte jo foarôf in protte leare.

Netwurk biblioteken

As jo ​​​​wat effisjinter nedich binne as TCP, mar jo net wolle lestich falle om jo eigen protokol te ymplementearjen en in protte details yn te gean, kinne jo de netbibleteek brûke. Der binne in protte fan harren:

Ik haw net besocht se allegearre, mar ik leaver ENet omdat it is maklik te brûken en betrouber. Derneist hat it dúdlike dokumintaasje en in tutorial foar begjinners.

Ferfier Protokol Konklúzje

Om gearfetsje, binne d'r twa haadferfierprotokollen: TCP en UDP. TCP hat in protte nuttige funksjes: betrouberens, behâld fan pakketopdracht, flaterdeteksje. UDP hat dat alles net, mar TCP, troch har aard, hat hege latency dy't net akseptabel is foar guon spultsjes. Dat is, om in lege latency te garandearjen, kinne jo jo eigen protokol oanmeitsje basearre op UDP of in bibleteek brûke dy't it transportprotokol op UDP ymplementearret en is oanpast foar multiplayer fideospultsjes.

De kar tusken TCP, UDP en de bibleteek hinget ôf fan ferskate faktoaren. Earst, út 'e behoeften fan it spul: hat it lege latency nedich? Twads, út 'e easken fan it tapassingsprotokol: hat it in betrouber protokol nedich? Lykas wy yn it folgjende diel sille sjen, is it mooglik om in applikaasjeprotokol te meitsjen wêrfoar in ûnbetrouber protokol hiel geskikt is. Uteinlik moatte jo ek de ûnderfining fan 'e ûntwikkelder fan' e netwurkmotor beskôgje.

Ik haw twa tips:

  • Abstraksje it ferfierprotokol safolle mooglik út 'e rest fan' e applikaasje, sadat it maklik kin wurde ferfongen sûnder alle koade opnij te skriuwen.
  • Net oeroptimalisearje. As jo ​​binne gjin netwurk saakkundige en binne net wis op oft jo nedich hawwe jo eigen UDP-basearre ferfier protokol, kinne jo begjinne mei TCP of in bibleteek dy't soarget foar betrouberens, en dan testen en mjitte prestaasjes. As jo ​​​​problemen hawwe en jo wis binne dat it in transportprotokol is, dan kin it tiid wêze om jo eigen ferfierprotokol te meitsjen.

Oan 'e ein fan dit diel ried ik oan dat jo lêze Yntroduksje ta Multiplayer Game Programming Brian Hook, dy't in protte fan 'e ûnderwerpen besprutsen hjir.

Applikaasjeprotokol

No't wy gegevens útwikselje kinne tusken kliïnten en de tsjinner, moatte wy beslute hokker gegevens oerdrage en yn hokker formaat.

De klassike skema is dat kliïnten stjoere input of aksjes nei de tsjinner, en de tsjinner stjoert de hjoeddeiske spultsje steat oan de kliïnten.

De tsjinner stjoert net de folsleine, mar de filtere steat mei entiteiten dy't tichtby de spiler. Hy docht dit om trije redenen. Earst kin de totale steat te grut wêze om op in hege frekwinsje te stjoeren. Twadder binne kliïnten benammen ynteressearre yn fisuele en audiogegevens, om't it grutste part fan 'e spiellogika wurdt simulearre op' e spielserver. Tredde, yn guon spultsjes hoecht de spiler bepaalde gegevens net te witten, lykas de posysje fan 'e fijân oan 'e oare kant fan 'e kaart, om't hy oars pakketten kin snuffelje en krekt wit wêr't er ferhúzje moat om him te deadzjen.

Serialisaasje

De earste stap is om de gegevens te konvertearjen dy't wy wolle ferstjoere (ynfier as spielstatus) yn in formaat dat geskikt is foar oerdracht. Dit proses wurdt neamd serialisaasje.

It idee komt daliks yn 't sin om in minsklik lêsber formaat te brûken, lykas JSON of XML. Mar dit sil folslein net effisjint wêze en sil it measte fan it kanaal foar neat opnimme.

Ynstee dêrfan is it oan te rieden om it binêre formaat te brûken, dat folle kompakter is. Dat is, de pakketten sille mar in pear bytes befetsje. Hjir moatte wy rekken hâlde mei it probleem byte oarder, dy't ferskille kinne op ferskate kompjûters.

Om gegevens te serialisearjen kinne jo in bibleteek brûke, bygelyks:

Soargje gewoan dat de bibleteek draachbere argiven makket en soarget foar endianness.

In alternative oplossing soe wêze om it sels te ymplementearjen, it is net sa dreech, foaral as jo in data-sintraal oanpak yn jo koade brûke. Derneist sil it jo mooglik meitsje om optimisaasjes út te fieren dy't net altyd mooglik binne by it brûken fan de bibleteek.

Glenn Fiedler hat twa artikels skreaun oer serialisaasje: Lêzen en skriuwen pakketten и Serialization Strategies.

Kompresje

De hoemannichte gegevens oerdroegen tusken kliïnten en de tsjinner wurdt beheind troch de bânbreedte fan it kanaal. Gegevenskompresje sil jo mear gegevens yn elke momintopname kinne oerdrage, de ferfarskingsfrekwinsje ferheegje, of gewoan de easken foar bânbreedte ferminderje.

Bytsje ynpakke

De earste technyk is bit packing. It bestiet yn it brûken fan krekt it oantal bits dat nedich is om de winske wearde te beskriuwen. Bygelyks, as jo in enum hawwe dy't 16 ferskillende wearden hawwe kinne, dan kinne jo yn stee fan in hiele byte (8 bits) mar 4 bits brûke.

Glenn Fiedler leit út hoe't jo dit útfiere kinne yn it twadde diel fan it artikel. Lêzen en skriuwen pakketten.

Bitferpakking wurket benammen goed mei diskretisaasje, dat sil it ûnderwerp wêze fan 'e folgjende seksje.

Sampling

Sampling is in lossy kompresjetechnyk dy't allinich in subset fan mooglike wearden brûkt om in wearde te kodearjen. De maklikste manier om diskretisaasje út te fieren is troch driuwende-puntnûmers ôf te rûnen.

Glenn Fiedler lit (wer!) sjen hoe't diskretisaasje yn 'e praktyk tapast wurde kin yn syn artikel Snapshot kompresje.

Kompresje algoritmen

De folgjende technyk sil ferliesleaze kompresjealgoritmen wêze.

Hjir binne nei myn miening de trije meast nijsgjirrige algoritmen dy't jo moatte witte:

  • Huffman kodearring mei precomputed koade, dat is ekstreem fluch en kin produsearje goede resultaten. It waard brûkt om pakketten yn 'e Quake3 netwurkmotor te komprimearjen.
  • zlib is in kompresjealgoritme foar algemien doel dat de hoemannichte gegevens nea fergruttet. Hoe kinne jo sjen hjir, it is brûkt yn in ferskaat oan tapassingen. Foar it bywurkjen fan steaten kin it oerstallich wêze. Mar it kin fan pas komme as jo aktiva, lange teksten of terrein moatte stjoere nei kliïnten fan 'e tsjinner.
  • It kopiearjen fan runlengten is nei alle gedachten de simpelste kompresje algoritme, mar it is hiel effisjint foar bepaalde soarten fan gegevens, en kin brûkt wurde as in pre-ferwurkjen stap foar zlib. It is benammen geskikt foar it komprimearjen fan terrein besteande út tegels of voxels wêryn in protte oanbuorjende eleminten wurde werhelle.

delta kompresje

De lêste kompresjetechnyk is delta-kompresje. It leit yn it feit dat allinnich de ferskillen tusken de hjoeddeiske spultsje steat en de lêste steat ûntfongen troch de klant wurde oerdroegen.

It waard earst brûkt yn 'e Quake3 netwurkmotor. Hjir binne twa artikels dy't útlizze hoe't jo it brûke:

Glenn Fiedler brûkte it ek yn it twadde diel fan syn artikel. Snapshot kompresje.

Fersifering

Derneist moatte jo miskien de oerdracht fan ynformaasje tusken kliïnten en de tsjinner fersiferje. D'r binne ferskate redenen foar dit:

  • Privacy / fertroulikens: Berjochten kinne allinich lêzen wurde troch de ûntfanger en gjin oare netwurksnuffer sil se lêze kinne.
  • autentikaasje: in persoan dy't wol spylje de rol fan in spiler moat witte syn kaai.
  • cheat previnsje: it sil folle dreger wêze foar kweade spilers om har eigen cheatpakketten te meitsjen, se moatte it fersiferingsskema replikearje en de kaai fine (dy't feroaret op elke ferbining).

Ik advisearje sterk in bibleteek te brûken foar dit. Ik stel foar gebrûk libsodium, om't it foaral ienfâldich is en geweldige tutorials hat. Benammen nijsgjirrich is de tutorial oer kaai ​​útwikseling, wêrtroch jo nije kaaien kinne generearje op elke nije ferbining.

Applikaasjeprotokol: Konklúzje

Dit konkludearret it tapassingsprotokol. Ik leau dat kompresje folslein opsjoneel is en it beslút om it te brûken hinget allinich ôf fan it spultsje en de fereaske bânbreedte. Fersifering, nei myn miening, is ferplicht, mar yn it earste prototype kinne jo sûnder it dwaan.

Applikaasje logika

Wy kinne no de steat yn 'e kliïnt bywurkje, mar wy kinne problemen mei latency hawwe. De spiler, nei it ynfieren, moat wachtsje op in update fan 'e spielstatus fan' e server om te sjen hokker ynfloed it hat op 'e wrâld.

Boppedat, tusken twa steat updates, de wrâld is folslein statysk. As de steat update taryf is leech, dan de bewegings sille wêze hiel jerky.

D'r binne ferskate techniken om de gefolgen fan dit probleem te ferminderjen, en ik sil se yn 'e folgjende paragraaf beprate.

Fertraging Smoothing Technieken

Alle techniken beskreaun yn dizze paragraaf wurde besprutsen yn detail yn de rige. Fast Paced Multiplayer Gabriel Gambetta. Ik riede tige oan om dizze treflike searje artikels te lêzen. It omfettet ek in ynteraktive demo om te sjen hoe't dizze techniken yn 'e praktyk wurkje.

De earste technyk is om it ynfierresultaat direkt oan te passen sûnder te wachtsjen op in antwurd fan 'e tsjinner. It hjit klant-side foarsizzing. As de kliïnt lykwols in update fan 'e tsjinner ûntfangt, moat it ferifiearje dat syn foarsizzing korrekt wie. As dit net it gefal is, dan moat hy gewoan syn steat feroarje neffens wat hy fan 'e tsjinner krige, om't de tsjinner autoritêr is. Dizze technyk waard earst brûkt yn Quake. Jo kinne der mear oer lêze yn it artikel. Quake Engine koade resinsje Fabien Sanglars [oersetting op Habré].

De twadde set techniken wurdt brûkt om de beweging fan oare entiteiten tusken twa steatupdates te glêdjen. D'r binne twa manieren om dit probleem op te lossen: ynterpolaasje en ekstrapolaasje. Yn it gefal fan ynterpolaasje wurde de lêste twa steaten nommen en de oergong fan de iene nei de oare wurdt toand. It neidiel dêrfan is dat it in lyts fraksje fan de fertraging soarget, om't de klant altyd sjocht wat der yn it ferline bard is. Ekstrapolaasje giet oer it foarsizzen fan wêr't de entiteiten no moatte wurde basearre op 'e lêste steat ûntfongen troch de klant. It neidiel is dat as de entiteit de bewegingsrjochting folslein feroaret, dan sil d'r in grutte flater wêze tusken de prognose en de echte posysje.

De lêste, meast avansearre technyk, brûkber allinnich yn FPS, is lag kompensaasje. By it brûken fan lagkompensaasje hâldt de tsjinner rekken mei de fertragingen fan 'e kliïnt as it op it doel sjit. Bygelyks, as in spiler in headshot op har skerm útfierde, mar yn 'e realiteit wie har doel op in oare lokaasje fanwegen de fertraging, dan soe it ûnrjochtfeardich wêze om de spiler it rjocht te wegerjen om te deadzjen fanwegen de fertraging. Sa spoelt de tsjinner de tiid werom nei doe't de spiler skeat om te simulearjen wat de spiler op har skerm seach en te kontrolearjen op in botsing tusken har skot en it doel.

Glenn Fiedler (lykas altyd!) skreau in artikel yn 2004 Network Physics (2004), wêryn hy de basis lei foar de syngronisaasje fan fysika-simulaasjes tusken de tsjinner en de kliïnt. Yn 2014 skreau er in nije searje artikels netwurkfysika, wêryn hy oare techniken beskreau foar syngronisaasje fan natuerkundesimulaasjes.

D'r binne ek twa artikels op Valve's wiki, Boarne Multiplayer Networking и Wachttiid kompensearjende metoaden yn Client / Server In-game Protocol Design and Optimization omgean mei fertraging fergoeding.

Cheat Previnsje

D'r binne twa wichtige techniken foar foarkommen fan fraude.

Earst, it meitsjen fan it dreger foar cheaters om kweade pakketten te stjoeren. Lykas hjirboppe neamd, is in goede manier om it út te fieren fersifering.

Twadder moat de autoritative tsjinner allinich kommando's / ynfier / aksjes ûntfange. De kliïnt moat de steat op 'e tsjinner net feroarje kinne oars as troch ynput te ferstjoeren. Dan moat de tsjinner, elke kear as er ynfier ûntfangt, it kontrolearje op jildichheid foardat it tapast.

Application Logic: Konklúzje

Ik riede oan dat jo in manier ymplementearje om hege latency en lege ferfarskingsnivo's te simulearjen, sadat jo it gedrach fan jo spultsje kinne testen yn minne omstannichheden, sels as de kliïnt en de tsjinner op deselde masine rinne. Dit simplifies de ymplemintaasje fan techniken foar fertraging glêdens sterk.

Oare Helpful Resources

As jo ​​​​oare boarnen fan netwurkmodel wolle ferkenne, kinne jo se hjir fine:

  • Glenn Fiedler's blog - it is it wurdich om syn hiele blog te lêzen, d'r binne in protte treflike artikels yn. it is alle artikels oer netwurk technologyen wurde sammele.
  • Awesome Game Networking troch M. Fatih MAR is in wiidweidige list fan artikels en fideo's oer fideospultsjes netwurkmotoren.
  • В wiki subreddit r/gamedev D'r binne ek in protte nuttige keppelings.

Boarne: www.habr.com

Add a comment