{"id":89303,"date":"2020-07-22T01:42:30","date_gmt":"2020-07-21T23:42:30","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency"},"modified":"2020-07-22T01:42:30","modified_gmt":"2020-07-21T23:42:30","slug":"oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\"><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nSoftware come servizio, infrastruttura come servizio, piattaforma come servizio, piattaforma di comunicazione come servizio, videoconferenze come servizio, e cosa dire del gaming in cloud come servizio? Ci sono state diverse iniziative per creare giochi in cloud (Cloud Gaming), come Stadia, recentemente lanciato da Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">non \u00e8 nuovo nel WebRTC<\/a><\/noindex>, ma possono gli altri utilizzare WebRTC allo stesso modo?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen ha deciso di esplorare questa possibilit\u00e0 nel suo progetto open source CloudRetro. CloudRetro si basa su Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">una popolare<\/a><\/noindex> libreria WebRTC basata su Go (grazie a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Sean<\/a><\/noindex> del team di sviluppo Pion per l'assistenza nella scrittura di questo articolo). In questo articolo, Thanh esamina l'architettura del suo progetto e condivide ci\u00f2 che ha trovato utile e le sfide affrontate durante il lavoro.<\/p>\n<h2>Introduzione<\/h2>\n<p>\nL'anno scorso, quando Google ha annunciato Stadia, sono rimasto completamente sbalordito. L'idea \u00e8 cos\u00ec unica e innovativa che mi sono continuamente chiesto come sia possibile con le tecnologie attuali. Il desiderio di capire meglio questo argomento mi ha spinto a creare la mia versione di un gioco cloud open source. Il risultato \u00e8 stato fantastico. Di seguito, vorrei condividere il processo di lavoro sul mio progetto annuale <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">progetto<\/a><\/noindex>.<\/p>\n<p><i>TLDR: versione breve con i punti salienti<\/i><\/p>\n<h3>Perch\u00e9 il futuro \u00e8 nei giochi cloud<\/h3>\n<p>\nCredo che il Cloud Gaming presto diventer\u00e0 la nuova generazione non solo di giochi, ma anche di altri settori informatici. I giochi cloud rappresentano l'apice del modello client\/server. Questo modello massimizza la gestione del back-end e minimizza il lavoro del front-end, posizionando la logica di gioco su un server remoto e trasmettendo in streaming immagini\/audio al client. Il server gestisce l'elaborazione intensa, quindi il client non \u00e8 pi\u00f9 vincolato dalle limitazioni hardware.<\/p>\n<p>Google Stadia, in sostanza, consente di giocare a <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/AAA_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8%D0%B3%D1%80%D1%8B)\">AAA-giocattoli<\/a><\/noindex> (ovvero giochi blockbuster di alta qualit\u00e0) su un'interfaccia simile a YouTube. La stessa metodologia pu\u00f2 essere applicata anche ad altre applicazioni pesanti offline, come il sistema operativo o il design grafico 2D\/3D, ecc., in modo da poterle eseguire in modo stabile su dispositivi con specifiche tecniche inferiori su diverse piattaforme.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nIl futuro di questa tecnologia: immaginate se Microsoft Windows 10 funzionasse nel browser Chrome?<\/p>\n<h3>I giochi cloud sono tecnicamente complessi<\/h3>\n<p>\nIl gaming \u00e8 uno di quei rari ambiti in cui \u00e8 necessaria una reazione rapida costante da parte dell'utente. Se occasionalmente ci troviamo di fronte a un ritardo di 2 secondi durante un clic sulla pagina, ci\u00f2 \u00e8 accettabile. I flussi video in diretta tendono a subire un ritardo di alcuni secondi, ma offrono comunque un uso ragionevole. Tuttavia, se un gioco ha frequentemente un ritardo di 500 ms, giocare diventa semplicemente impossibile. Il nostro obiettivo \u00e8 raggiungere un ritardo estremamente basso, in modo che il divario tra input e media sia il pi\u00f9 ridotto possibile. Pertanto, l'approccio tradizionale al video in streaming qui non \u00e8 applicabile.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nModello generale di gioco cloud<\/p>\n<h2>Progetto open source CloudRetro<\/h2>\n<p>\nHo deciso di creare un campione test di gioco in cloud per verificare se tutto questo sia possibile con cos\u00ec rigide limitazioni di rete. Per testare il concetto, ho scelto Golang, poich\u00e9 \u00e8 il linguaggio a me pi\u00f9 familiare e si adatta bene a questa implementazione per molti altri motivi, come scoperto successivamente. Go \u00e8 semplice e si sviluppa molto rapidamente; i canali in Go sono perfetti per la gestione della multithreading.<\/p>\n<p>Progetto <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 un servizio di gioco in cloud con codice sorgente aperto per giochi retro. L'obiettivo del progetto \u00e8 portare nelle tradizionali esperienze di gioco retro il massimo del comfort e aggiungere il multiplayer.<br \/>\n\u00c8 possibile approfondire il progetto qui: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Funzionalit\u00e0 di CloudRetro<\/h3>\n<p>\nPer dimostrare tutta la potenza dei giochi in cloud, CloudRetro utilizza giochi retro. Questo consente di ottenere una serie di esperienze di gioco uniche.<\/p>\n<ul>\n<li>Portabilit\u00e0 del gioco\n<ul>\n<li>Riproduzione istantanea all'apertura della pagina; non \u00e8 necessaria n\u00e9 il caricamento n\u00e9 l'installazione<\/li>\n<li>Funziona nel browser mobile, quindi non \u00e8 necessario alcun software per avviare<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Le sessioni di gioco possono essere condivise su pi\u00f9 dispositivi e memorizzate nel cloud per il prossimo accesso.<\/li>\n<li>Il gioco pu\u00f2 essere trasmesso in streaming e giocato da pi\u00f9 utenti contemporaneamente:\n<ul>\n<li>Crowdplay tipo TwitchPlayPokemon, ma pi\u00f9 cross-platform e in tempo reale.<\/li>\n<li>Giochi offline online. Molti utenti possono giocare senza configurare la rete. In Samurai Shodown ora possono giocare 2 giocatori tramite CloudRetro.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVersione demo di un gioco multiplayer online su diversi dispositivi.<\/p>\n<h2>Infrastruttura<\/h2>\n<p><\/p>\n<h3>Requisiti e stack tecnologico.<\/h3>\n<p>\nDi seguito \u00e8 riportato un elenco di requisiti che ho impostato prima di iniziare il progetto.<\/p>\n<p><b>1. Un giocatore.<\/b><br \/>\nQuesto requisito potrebbe sembrare non cos\u00ec importante e ovvio qui, ma \u00e8 una delle mie conclusioni chiave; consente ai giochi in cloud di stare il pi\u00f9 lontano possibile dai tradizionali servizi di streaming. Se ci concentriamo sui giochi per un solo giocatore, possiamo eliminare il server centralizzato o il CDN, poich\u00e9 non abbiamo bisogno di trasmettere a masse. Invece di caricare i flussi su un server dedicato o inviare pacchetti a un server WebSocket centralizzato, i flussi di servizio vengono inviati all'utente direttamente attraverso una connessione peer-to-peer WebRTC.<\/p>\n<p><b>2. Flusso multimediale a bassa latenza<\/b><br \/>\nLeggendo di Stadia, incontro spesso in alcuni articoli un riferimento a WebRTC. Ho capito che WebRTC \u00e8 una tecnologia eccezionale e si adatta perfettamente all'uso nei giochi in cloud. WebRTC \u00e8 un progetto che fornisce ai browser web e alle app mobili comunicazione in tempo reale attraverso una semplice API. Fornisce una connessione peer-to-peer, ottimizzata per i media, con codec standard integrati come VP8 e H264.<\/p>\n<p>Ho dato priorit\u00e0 a garantire il massimo comfort agli utenti piuttosto che mantenere un'elevata qualit\u00e0 grafica. L'algoritmo ammette alcune perdite. In Google Stadia c'\u00e8 un passaggio aggiuntivo per ridurre le dimensioni dell'immagine sul server, e i frame vengono scalati a una qualit\u00e0 superiore prima di essere trasmessi ai nodi peer-to-peer.<\/p>\n<p><b>3. Infrastruttura distribuita con instradamento geografico<\/b><br \/>\nIndipendentemente da quanto sia ottimizzato l'algoritmo di compressione e il codice, la rete rimane il fattore cruciale che contribuisce maggiormente alla latenza. L'architettura deve prevedere un meccanismo di accoppiamento del server pi\u00f9 vicino all'utente per ridurre il tempo di andata e ritorno (RTT). L'architettura deve avere 1 coordinatore e diversi server di streaming distribuiti in tutto il mondo: Ovest degli Stati Uniti, Est degli Stati Uniti, Europa, Singapore, Cina. Tutti i server di streaming devono essere completamente isolati. Il sistema pu\u00f2 regolare la sua distribuzione quando un server si unisce o si disconnette dalla rete. Pertanto, in caso di elevato traffico, l'aggiunta di server aggiuntivi consente di effettuare scalabilit\u00e0 orizzontale.<\/p>\n<p><b>4. Compatibilit\u00e0 del browser<\/b><br \/>\nI giochi in cloud brillano al meglio quando richiedono un minimo ai giocatori. Questo significa che possono essere avviati direttamente nel browser. I browser rendono l'esperienza di gioco il pi\u00f9 confortevole possibile per gli utenti, liberandoli dall'installazione di software e hardware. Inoltre, i browser garantiscono la compatibilit\u00e0 tra piattaforme per le versioni mobile e desktop. Fortunatamente, WebRTC \u00e8 ben supportato in vari browser.<\/p>\n<p><b>5. Chiara separazione tra l'interfaccia di gioco e il servizio<\/b><br \/>\nConsidero il servizio di giochi in cloud come una piattaforma. Ognuno dovrebbe avere la possibilit\u00e0 di collegare qualsiasi cosa alla piattaforma. Attualmente ho integrato <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> con il servizio di giochi in cloud, poich\u00e9 LibRetro offre una bellissima interfaccia di emulatore per giochi retro come SNES, GBA e PS.<\/p>\n<p><b>6. Stanze per multiplayer, crowd play e deep linking con il gioco<\/b><br \/>\nCloudRetro supporta molte nuove modalit\u00e0 di gioco, come CrowdPlay e Multiplayer Online per i giochi retro. Se pi\u00f9 utenti aprono lo stesso deep link su computer diversi, vedranno lo stesso gioco avviato e potranno anche unirsi.<\/p>\n<p>Inoltre, gli stati di gioco sono memorizzati nel cloud. Questo consente agli utenti di continuare a giocare in qualsiasi momento su qualsiasi altro dispositivo.<\/p>\n<p><b>7. Scalabilit\u00e0 orizzontale<\/b><br \/>\nCome qualsiasi SAAS al giorno d'oggi, i giochi in cloud devono essere progettati per essere scalabili orizzontalmente. La struttura \"coordinatore-lavoratore\" consente di aggiungere pi\u00f9 lavoratori per gestire un traffico maggiore.<\/p>\n<p><b>8. Nessun legame con un solo cloud<\/b><br \/>\nL'infrastruttura CloudRetro \u00e8 ospitata su diversi fornitori di cloud (Digital Ocean, Alibaba, fornitore personalizzato) per diverse regioni. Attivo l'avvio in un contenitore Docker per l'infrastruttura e configuro i parametri di rete utilizzando uno script bash, per evitare la dipendenza da un unico fornitore di cloud. Combinando questo con NAT Traversal in WebRTC, possiamo ottenere flessibilit\u00e0 per distribuire CloudRetro su qualsiasi piattaforma cloud e persino su macchine di qualsiasi utente.<\/p>\n<h3>Design architettonico<\/h3>\n<p>\n<b>Lavoratore:<\/b> (o server di streaming menzionato sopra) moltiplica i giochi, lancia il pipeline di codifica e trasmette i media codificati agli utenti. Le istanze del worker sono distribuite in tutto il mondo, e ogni worker pu\u00f2 gestire pi\u00f9 sessioni utente contemporaneamente.<\/p>\n<p><b>Coordinatore:<\/b> si occupa di abbinare un nuovo utente al worker pi\u00f9 adatto per lo streaming. Il coordinatore interagisce con i worker tramite WebSocket.<\/p>\n<p><b>Archivio degli stati di gioco:<\/b> un archivio remoto centrale per tutti gli stati del gioco. Questo archivio offre funzioni importanti come il salvataggio e il caricamento remoto.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nArchitettura di alto livello di CloudRetro<\/p>\n<h3>Caso d'uso<\/h3>\n<p>\nQuando un nuovo utente apre CloudRetro nei passaggi 1 e 2 mostrati nell'immagine qui sotto, il coordinatore richiede la prima pagina insieme all'elenco dei lavoratori disponibili. Successivamente, nel passaggio 3, il cliente calcola i ritardi per tutti i candidati utilizzando una richiesta HTTP ping. Questo elenco di ritardi viene quindi inviato nuovamente al coordinatore, in modo che possa determinare il lavoratore pi\u00f9 adatto per assistere l'utente. Nel passaggio 4 qui sotto viene creata una partita. Viene stabilita una connessione in streaming WebRTC tra l'utente e il lavoratore assegnato.<br \/>\n<img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nFlusso utente dopo aver ottenuto l'accesso<\/p>\n<h3>Cosa c'\u00e8 all'interno del lavoratore<\/h3>\n<p>\nI pipeline di gioco e streaming sono conservati all'interno del lavoratore in modo isolato e scambiano informazioni tramite un'interfaccia. Attualmente, questa connessione avviene tramite il trasferimento dati in memoria attraverso <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">canali Golang<\/a><\/noindex> nello stesso processo. Il prossimo obiettivo \u00e8 la segregazione, ossia l'esecuzione indipendente della partita in un altro processo.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInterazione tra i componenti del lavoratore<\/p>\n<p>Componenti principali:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> componente client che riceve l'input dell'utente ed emette media codificato dal server.\n<\/li>\n<li><b>Emulatore di gioco:<\/b> componente di gioco. Grazie alla libreria Libretro, il sistema \u00e8 in grado di eseguire il gioco all'interno dello stesso processo e di intercettare internamente media e flussi di input.\n<\/li>\n<li>I fotogrammi in-game vengono catturati e inviati al codificatore.\n<\/li>\n<li><b>Codificatore di immagine\/audio:<\/b> pipeline di codifica che riceve i fotogrammi multimediali, li codifica in background e produce immagini\/audio codificati.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementazione<\/h2>\n<p>\nCloudRetro fa affidamento su WebRTC come tecnologia di trasporto principale, quindi prima di approfondire i dettagli dell'implementazione in Golang, ho deciso di parlare di WebRTC stesso. \u00c8 una tecnologia straordinaria che mi ha aiutato a raggiungere una latenza della trasmissione dei dati di solo una frazione di secondo.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC \u00e8 progettato per fornire connessioni peer-to-peer di alta qualit\u00e0 su app mobili native e nei browser tramite API semplici.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC \u00e8 noto per la sua funzionalit\u00e0 di NAT Traversal. WebRTC \u00e8 progettato per la comunicazione peer-to-peer. Il suo obiettivo \u00e8 trovare il percorso diretto pi\u00f9 appropriato, evitando gateway NAT e firewall per le comunicazioni peer-to-peer attraverso un processo chiamato <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. Nell'ambito di questo processo, l'API WebRTC rileva il tuo indirizzo IP pubblico utilizzando i server STUN e lo reindirizza a un server di retransmission (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), quando non pu\u00f2 essere stabilita una connessione diretta.<\/p>\n<p>Tuttavia, CloudRetro non sfrutta appieno questa capacit\u00e0. Le sue connessioni peer-to-peer non avvengono tra utenti, ma tra utenti e server cloud. La parte server del modello ha meno vincoli sulla connessione diretta rispetto ai normali dispositivi degli utenti. Ci\u00f2 consente di effettuare l'apertura preliminare delle porte in ingresso o di utilizzare indirizzi IP pubblici direttamente, poich\u00e9 il server non \u00e8 dietro un NAT.<\/p>\n<p>In passato volevo trasformare il progetto in una piattaforma per la distribuzione di giochi nel Cloud Gaming. L'idea era di consentire ai creatori di giochi di fornire giochi e risorse di streaming. Gli utenti avrebbero interagito direttamente con i fornitori. In questo modo decentralizzato, CloudRetro \u00e8 solo un ambiente per collegare risorse di streaming di terze parti agli utenti, rendendolo pi\u00f9 scalabile poich\u00e9 il servizio di hosting non \u00e8 pi\u00f9 un ostacolo. Il ruolo del WebRTC NAT Traversal \u00e8 fondamentale per facilitare l'inizializzazione di una connessione peer-to-peer su risorse di streaming di terze parti, semplificando il collegamento tra il creatore e la rete.<\/p>\n<h4>Compressione video<\/h4>\n<p>\nLa compressione video \u00e8 una parte essenziale del pipeline che contribuisce in larga misura alla fluidit\u00e0 dello streaming. Anche se non \u00e8 necessario conoscere tutti i dettagli della codifica video in VP8\/H264, comprendere il concetto aiuta a navigare i parametri di bitrate dello streaming video, risolvere comportamenti inaspettati e ottimizzare la latenza.<\/p>\n<p>La compressione video per lo streaming \u00e8 una sfida complessa, poich\u00e9 l'algoritmo deve garantire che il tempo totale di codifica + tempo di trasmissione in rete + tempo di decodifica sia il pi\u00f9 ridotto possibile. Inoltre, il processo di codifica deve essere coerente e continuo. Alcuni compromessi durante la codifica non sono accettabili: ad esempio, non possiamo privilegiare un tempo di codifica pi\u00f9 lungo a favore di una dimensione del file pi\u00f9 piccola e di un tempo di decodifica inferiore, n\u00e9 utilizzare una compressione incoerente.<\/p>\n<p>L'idea alla base della compressione video \u00e8 quella di escludere i bit di informazione non necessari, mantenendo per\u00f2 un livello di precisione accettabile per gli utenti. Oltre a codificare singoli fotogrammi statici, l'algoritmo trae conclusioni per il fotogramma corrente dai fotogrammi precedenti e successivi, inviando solo le loro differenze. Come si pu\u00f2 vedere dall'esempio con Pacman, vengono trasmesse solo le differenze.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nConfronto dei fotogrammi video con l'esempio di Pacman<\/p>\n<h4>Compressione audio<\/h4>\n<p>\nSimilarmente, l'algoritmo di compressione audio esclude i dati che non possono essere percepiti dall'orecchio umano. Opus \u00e8 attualmente il codec audio con le migliori prestazioni. \u00c8 progettato per trasmettere onde sonore attraverso un protocollo di datagramma ordinato, come RTP (Real Time Transport Protocol \u2013 protocollo di trasporto in tempo reale). La sua latenza \u00e8 inferiore a quella di mp3 e aac, e la qualit\u00e0 \u00e8 superiore. La latenza \u00e8 normalmente di circa 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC in Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> \u00e8 un progetto open source che porta WebRTC su Golang. Invece di avvolgere le librerie C++ native di WebRTC, Pion \u00e8 una realizzazione nativa di WebRTC in Golang con prestazioni superiori, integrazione con Go e controllo delle versioni sui protocolli WebRTC.<\/p>\n<p>La libreria offre anche lo streaming con molti moduli integrati eccellenti, con una latenza inferiore a un secondo. Dispone di una propria implementazione di STUN, DTLS, SCTP, ecc. e ha fatto alcune sperimentazioni con QUIC e WebAssembly. Questa libreria open source \u00e8 davvero una buona risorsa per l'apprendimento, con un'ottima documentazione, implementazione di protocolli di rete e interessanti esempi.<\/p>\n<p>La comunit\u00e0 Pion, guidata da un creatore molto appassionato, \u00e8 piuttosto vivace, con molte discussioni di qualit\u00e0 su WebRTC. Se sei interessato a questa tecnologia, unisciti a <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 imparerai molte cose nuove.<\/p>\n<h3>Scrivere CloudRetro in Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementazione di un worker in Go<\/p>\n<h4>Canali Go in azione<\/h4>\n<p>\nGrazie al design intuitivo dei canali Go, le problematiche di streaming degli eventi e di parallelismo sono notevolmente semplificate. Come illustrato nel diagramma, pi\u00f9 componenti operano in parallelo all'interno di diverse GoRoutines. Ogni componente gestisce il proprio stato e comunica tramite i canali. L'affermazione selettiva di Golang obbliga a trattare un solo evento atomico per ogni tick di gioco. Questo implica che per tale design non \u00e8 necessaria alcuna esclusione. Ad esempio, quando un giocatore salva, \u00e8 necessario un snapshot completo dello stato di gioco. Questo stato deve rimanere coerente, eseguendo input fino a quando il salvataggio non \u00e8 completo. Durante ogni tick di gioco, il backend pu\u00f2 gestire solo l'operazione di salvataggio o l'input, rendendo il processo thread-safe.<\/p>\n<pre><code class=\"go\">func (e *gameEmulator) gameUpdate() {\nfor {\n\tselect {\n\t\tcase &lt;-e.saveOperation:\n\t\t\te.saveGameState()\n\t\tcase key := &lt;-e.input:\n\t\t\te.updateGameState(key)\n\t\tcase &lt;-e.done:\n\t\t\te.close()\n\t\t\treturn\n\t}\n    }\n}<\/code><\/pre>\n<p><\/p>\n<h4>Fan-in \/ Fan-out<\/h4>\n<p>\nQuesto template Golang si adatta perfettamente al mio caso d'uso di CrowdPlay e Multiplayer. Seguendo questo schema, tutti gli input degli utenti in una stanza vengono incorporati nel canale centrale di ingresso. I media di gioco vengono quindi distribuiti a tutti gli utenti in una stanza. In questo modo, otteniamo una separazione dello stato di gioco tra pi\u00f9 sessioni di gioco di utenti diversi.<\/p>\n<p><img decoding=\"async\" alt=\"Gaming in cloud con codice aperto su WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSincronizzazione tra diverse sessioni<\/p>\n<h4>Svantaggi di Golang<\/h4>\n<p>\nGolang non \u00e8 perfetto. Il canale \u00e8 lento. Rispetto ai blocchi, il canale Go \u00e8 semplicemente un modo pi\u00f9 semplice per gestire eventi paralleli e in streaming, ma il canale non fornisce le migliori prestazioni. Dietro il canale c'\u00e8 una logica complessa di blocco. Pertanto, ho apportato alcune modifiche all'implementazione, riapplicando i blocchi e i valori atomici per sostituire i canali e ottimizzare le prestazioni.<\/p>\n<p>Inoltre, il garbage collector in Golang \u00e8 incontrollato, il che porta a pause sospette e lunghe in alcuni casi. Questo interferisce notevolmente con le prestazioni delle applicazioni in tempo reale.<\/p>\n<h4>CGO<\/h4>\n<p>\nIl progetto utilizza la libreria open source VP8\/H264 di Golang per la compressione dei media e Libretro per gli emulatori di giochi. Tutte queste librerie sono semplici wrapper della libreria C in Go, utilizzando <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Alcuni dei difetti sono elencati in <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">questo post di Dave Cheney<\/a><\/noindex>. I problemi che ho incontrato sono stati:<\/p>\n<ul>\n<li>impossibilit\u00e0 di catturare crash in CGO, anche con Golang RecoveryCrash;<\/li>\n<li>impossibilit\u00e0 di identificare il collo di bottiglia delle prestazioni, quando non possiamo rilevare problemi dettagliati in CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclusione<\/h2>\n<p>\nHo raggiunto il mio obiettivo: ho esplorato i servizi di gioco cloud e creato una piattaforma che permette di giocare a giochi retro nostalgici con i miei amici online. Creare questo progetto sarebbe stato impossibile senza la libreria Pion e il supporto della comunit\u00e0 Pion. Sono estremamente grato per il suo intenso sviluppo. Le semplici API fornite da WebRTC e Pion hanno consentito un'integrazione fluida. Il mio primo proof of concept \u00e8 stato rilasciato nella stessa settimana, nonostante non avessi informazioni preliminari sulla connessione peer-to-peer (P2P).<\/p>\n<p>Nonostante la semplicit\u00e0 di integrazione, lo streaming P2P \u00e8 davvero un campo molto complesso nell'informatica. Deve affrontare la complessit\u00e0 di architetture di rete consolidate, come IP e NAT, per creare una sessione peer-to-peer. Durante il lavoro su questo progetto, ho accumulato molte conoscenze preziose sulla rete e sull'ottimizzazione delle prestazioni, quindi raccomando a tutti di provare a costruire prodotti P2P utilizzando WebRTC.<\/p>\n<p>CloudRetro copre tutti gli scenari d'uso che mi aspettavo, dal mio punto di vista, come appassionato di retro gaming. Tuttavia, penso che ci siano molte aree nel progetto che posso migliorare, come rendere la rete pi\u00f9 affidabile e performante, garantire una qualit\u00e0 grafica superiore nei giochi o la possibilit\u00e0 di condividere giochi tra utenti. Sto lavorando duramente su questo. Per favore, rimanete sintonizzati su <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">progetto<\/a><\/noindex> e supportatelo se vi piace.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":89304,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-89303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Gaming cloud open-source su WebRTC: p2p, multiplayer, zero latenza | ProHoster","description":"PO come servizio, infrastruttura come servizio, piattaforma come servizio, piattaforma di comunicazione come servizio, videoconferenze come servizio, e che dire del gaming cloud come servizio? Sono gi\u00e0 stati fatti diversi tentativi di creare giochi cloud (Cloud Gaming), ad esempio, Stadia, recentemente lanciata da Google. Stadia non \u00e8 nuova a WebRTC, ma possono gli altri utilizzare WebRTC allo stesso modo? Thanh Nguyen (Thanh","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster","og:description":"\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-21T23:42:30+00:00","article:modified_time":"2020-07-21T23:42:30+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"89303","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:12:27","updated":"2022-09-29 13:03:06"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}