Come scrivere un gioco di rete? [chiuso]


73

Basato su Perché è così difficile sviluppare un MMO? :

Lo sviluppo di giochi in rete non è banale; ci sono grandi ostacoli da superare non solo in termini di latenza, ma anche di prevenzione degli imbrogli, gestione dello stato e bilanciamento del carico. Se non hai esperienza con la scrittura di un gioco in rete, questo sarà un esercizio di apprendimento difficile.

Conosco la teoria su socket, server, client, protocolli, connessioni e cose del genere.

Ora mi chiedo come si possa imparare a scrivere un gioco di rete:

  • Come bilanciare i problemi di carico?
  • Come gestire lo stato del gioco?
  • Come mantenere le cose sincronizzate?
  • Come proteggere la comunicazione e il cliente dal reverse engineering?
  • Come aggirare i problemi di latenza?
  • Quali cose dovrebbero essere calcolate localmente e quali cose sul server?
  • ...

Ci sono buoni libri, tutorial, siti, articoli interessanti o altre domande a riguardo?

Sto cercando risposte ampie, ma anche quelle specifiche vanno bene per imparare la differenza.


4
Sì, ci sono libri, tutorial, siti, articoli interessanti e altre domande a riguardo.
Ricket,

2
Ho aggiunto generosità per spingere la domanda senza modificarla e dare agli utenti un motivo per rispondere poiché questa domanda merita risposte, quindi il miglior risponditore ottiene reputazione per il proprio lavoro, ma non esiste una sola risposta che risponda alla domanda.
Tamara Wijsman,

Risposte:


61

Oltre all'articolo collegato in altre risposte, posso dire qualcosa sull'esperienza del Progetto Arianne .

Come mantenere le cose sincronizzate?

Abbiamo creato un framework " Marauroa " attorno al concetto di azioni e percezioni: le azioni vengono inviate dal client al server portando l'input dell'utente come (cammina a sinistra, attacca i mostri n. 47, dì "ciao"). E le percezioni vengono inviate dal server ai client raccontando loro lo stato del mondo da vicino. Queste percezioni vengono inviate ad ogni turno. A seconda del gioco utilizziamo tempi di virata da 30ms a 300ms.

Abbiamo due tipi di percezioni : una percezione completa viene inviata al momento del login e quando il giocatore entra in una nuova area (zona). Successivamente vengono inviate percezioni differenziali che includono solo gli attributi modificati (ad es. Posizione) degli oggetti modificati e, naturalmente, oggetti nuovi e rimossi.

Come aggirare i problemi di latenza?

Crediamo fortemente in "il server ha sempre ragione". Il cliente fa alcune previsioni come camminata regolare, controlli delle collisioni e così via. Ma se un client e il server non sono d'accordo su qualcosa, il server vince. Il sottoprogetto Stendhal (un gioco di ruolo 2D) utilizza per impostazione predefinita un tempo di virata di 300 ms (con molto livellamento sul lato client). Questo rende Stendhal molto resistente al ritardo.

Nota: alcuni altri giochi si affidano in qualche modo al client per ridurre al minimo l'impatto del ritardo di rete. In WoW veniva spesso sfruttato in uno dei campi di battaglia chiamato "Warsong Gulch". Ci sono due modi in cui un giocatore con la bandiera può scegliere: Attivo nel mezzo attraverso un tunnel e uno sulla vista giusta salendo la collina. Quindi un giocatore che imbroglia corre verso il tunnel e poi provoca ritardi per se stesso. Il server e gli altri client continueranno a vederlo correre verso di esso. Ma dopo un po 'di tempo questo client può dire al server che è andato verso la collina. WoW verificherà che la distanza tra le ultime coordinate trasmesse e quelle attuali si adatti al segmento temporale e lo accetterà.

Uso di UDP vs. TCP

Nelle prime versioni abbiamo usato UDP per ridurre il sovraccarico di TCP. Abbiamo gestito i pacchetti persi per conto nostro. Questo ha funzionato perfettamente ai primi giorni del progetto. Ma quando diversi anni fa il server è stato spostato da una connessione DSL domestica a un vero data center, abbiamo riscontrato enormi problemi. UDP è (o almeno lo era 5 anni fa) estremamente esigente per la potenza della CPU dell'hardware del firewall: il set di regole deve essere applicato a ogni singolo pacchetto UDP. Per TCP, tuttavia, il set di regole viene applicato solo per i primi 3 pacchetti. Dopodiché viene stabilita la connessione. Tutti i pacchetti seguenti ignoreranno il normale set di regole perché si trovano nella tabella di tracciamento della connessione o perché non hanno un flag SYN.

Come proteggere la comunicazione e il cliente dal reverse engineering?

Arianne è completamente open source, questo include client, server, grafica, musica. E ovviamente questo include la documentazione del nostro protocollo e persino un analizzatore utilizzato per il debug.

È facile proteggere la comunicazione dallo sniffing non autorizzato da parte di terzi tramite SSL.

Tuttavia, è impossibile proteggerlo dal reverse engineering. Sicuro che puoi offuscarlo e usare tecniche di anti-debugging. Ma alla fine non puoi impedire il reverse engineering del software che dai agli utenti. C'è una presentazione molto interessante su come Skype è stato invertito, nonostante gli sviluppatori abbiano fatto un grande sforzo nelle tecniche di debug: http://recon.cx/en/f/vskype-part1.pdf

Nota: ci sono alcuni paesi in cui il reverse engineering è illegale o che consente di inserire un paragrafo nella licenza o di vietare il reverse engineering. Ma ci sono altri paesi (come quello in cui vivo) che consentono esplicitamente il reverse engineering nel contesto dello sviluppo di formati di archiviazione dei dati compatibili o protocolli di trasmissione, paragrafi nella licenza o ToS che cercano di non consentire che siano nulli. (Tutto in questa sezione è per quanto ne so, non sono un avvocato)

Quali cose dovrebbero essere calcolate localmente e quali cose sul server?

Calcoliamo tutto ciò che riguarda la logica di gioco sul server. Il cliente predirà determinati eventi per rendere il gioco fluido. Ma alla fine il server ha sempre ragione.

Gli eventi previsti sono, ad esempio, l'arresto del movimento quando viene colpita una collisione. Stendhal utilizza una griglia per posizionare gli elementi. E dal punto di vista del server, l'angolo in alto a sinistra di ogni entità si trova esattamente su un quadrato. Ma il cliente li sposterà senza problemi tra le tessere. Disegnerà anche l'effetto pseudo 3d. Quindi un'entità che ha una base di 1x1 può essere più alta nel client.

Come bilanciare i problemi di carico?

Cerca di mantenerlo il più semplice possibile, per facilitare la manutenzione.

Il bilanciamento del carico di contenuto statico è ben noto nell'area dei cluster di server http e delle reti di distribuzione del contenuto.

Un concetto piuttosto semplice per il bilanciamento del carico dei servizi di gioco è quello di dividere i server tra regioni / zone. Quindi le zone AC sono su un server e le zone DF su un altro. Ciò è particolarmente semplice se non puoi guardare dalle zone di un set alle zone di un altro set. È necessario inserire alcuni controlli in modo che un client possa connettersi solo a un server di zona responsabile della zona in cui si trova il giocatore.

Il modo più semplice per trasferire i giocatori da un server all'altro è di scriverli nel database, dire al client di connettersi all'altro server di zona e disconnetterli da quello corrente. Il client si connetterà quindi al nuovo server di zona che lo caricherà dal database. (Poiché è comunque necessario caricare / archiviare il codice del database, la comunicazione diretta tra i server per la consegna può essere implementata in un secondo momento).

Alcuni servizi globali aggiuntivi sono necessari tramite: All'accesso è necessario comunicare ai client di connettersi al server di zona corretto. E potresti desiderare un sistema di chat mondiale.

Ho approfondito questo argomento in Come si ottiene il bilanciamento del carico negli MMO?


1
Hai detto che UDP richiede un po 'più di CPU, ma non hai menzionato il fatto che TCP richiede almeno tre viaggi tra il client e il server prima che il pacchetto venga elaborato, E i pacchetti vengono bufferizzati fino a quando non sono stati ricevuti tutti i pacchetti precedenti, il che significa che potresti riscontrare ridicoli quantità di ritardo in attesa di pacchetti che non sono nemmeno più rilevanti. Sembra una cosa importante da menzionare.
BlueRaja - Danny Pflughoeft,

2
@Danny, sono necessari tre pacchetti per avviare una nuova connessione TCP: client-server: SYN, server-client: SYN ACK, client-server: ACK + dati. Questo è un round trip in più di UDP, ma succede solo all'inizio quando il client contatta il server per la prima volta. In una connessione stabilita ogni pacchetto viene elaborato immediatamente senza ulteriori round trip. Ci sarà una risposta ACK ma che i dati ricevuti sono già elaborati mentre i pacchetti ACK viaggiano indietro.
Hendrik Brummermann,

1
@Danny, TCP gestisce la perdita di pacchetti automaticamente e in modo abbastanza efficiente. È difficile reimplementare te stesso usando UDP; a meno che il protocollo non vada bene con i pacchetti casuali non consegnati. Il prossimo problema è che TCP garantisce che l'ordine dei pacchetti, mentre i pacchetti UDP possano essere ricevuti nell'ordine sbagliato. Ancora una volta, è difficile reimplementarlo da soli, a meno che non si possa semplicemente ignorare i pacchetti più vecchi, ad esempio in base a un contatore di pacchetti. Se per TCP è richiesto un tempo di risposta molto breve, l'algoritmo di Nagle deve essere disabilitato.
Hendrik Brummermann,

Sembra che tu abbia difeso con veemenza la tua posizione senza affrontare il vero problema del ritardo TCP. Forse il vero problema è la scelta di un firewall hardware invece di un protocollo DDoS resistente
MickLH

27

http://gafferongames.com/networking-for-game-programmers/

È un grande insieme di articoli su vari problemi e soluzioni che riguardano la rete di giochi.


1
+1, ma per favore non fidarti di loro ciecamente. Secondo la mia esperienza, ad esempio, non è una buona idea usare UDP e reinventare la funzionalità di TCP. L'UPD è utile solo se i pacchetti persi non hanno alcun impatto, ovvero ogni pacchetto UDP contiene lo stato rilevante completo del mondo. WoW utilizza TCP, SL è in procinto di passare da UDP a TCP (anche HTTP per contenuto statico) e ha migliorato significativamente le prestazioni con queste modifiche.
Hendrik Brummermann,

7
Tuttavia non stai reinventando le funzionalità TCP, non tutte almeno. Il controllo del flusso TCP e la semantica della perdita di pacchetti sono terribili per un gioco che richiede una connessione a bassa latenza. TCP è utile solo se non ti interessa la latenza o la riduzione della larghezza di banda richiesta.
jsimmons,

2
Second Life ha migliorato notevolmente le prestazioni passando da UDP a HTTP su TCP: blogs.secondlife.com/community/technology/blog/2010/08/13/…
Hendrik Brummermann

5
Non proprio, hanno migliorato le prestazioni del loro streaming di risorse cambiando il modo in cui funziona. L'uso di HTTP / TCP in quell'istanza ha reso più semplice l'implementazione, non più veloce. Potrei anche notare che zeromq è un progetto interessante e può adattarsi molto bene alla rete di giochi. zeromq.org
jsimmons

8

A seconda del tipo di gioco che stai scrivendo, potresti essere in grado di evitare alcune delle programmazioni di rete di basso livello. Alcuni tipi di giochi non richiedono molte comunicazioni avanti e indietro tra i client e il server. In tali casi, si potrebbe scegliere di utilizzare un framework di livello superiore. Ad esempio, sto sviluppando un gioco di strategia a turni in C # /. NET. I giochi di strategia a turni sono in qualche modo unici in quanto la stragrande maggioranza delle comunicazioni client / server avviene all'inizio e alla fine di un turno, con relativamente poco in mezzo. Pertanto, ho scelto di utilizzare Windows Communication Foundation (WCF), un framework di comunicazione di alto livello progettato principalmente per i servizi Web. Invece di lavorare direttamente con i socket e tutto quel gunk di rete di basso livello, posso fare quelle che sembrano chiamate di metodi standard, e lascia che WCF gestisca il protocollo e i livelli di trasporto per me. L'unica volta che ho avuto a che fare con le cose di rete di basso livello è stato quando ho configurato i miei endpoint, che è praticamente un affare una tantum in un file di configurazione. Potrebbe essere ancora necessario implementare una logica di serializzazione personalizzata, ma dovresti fare quel genere di cose a prescindere.


8

La domanda è troppo ampia. Le risposte potrebbero riempire un sito Web da sole. Ma ci sono libri che toccano questo, principalmente questi due:

Nota che anche questi libri non sono una guida completa, ma sono invece una raccolta di idee e approcci che puoi utilizzare, alcuni dei quali non funzionano insieme o sono persino contraddittori. In genere presuppone una certa esperienza nello sviluppo di giochi, applicazioni di rete o idealmente entrambi.

(Nota che sto parlando di più sugli MMO nella domanda originale: un "gioco di rete" potrebbe significare ogni sorta di cose da un gioco di testo basato su PHP fino a un MMO, e le domande secondarie sopra non tutte applicare a ciascun tipo.)


7

Come bilanciare i problemi di carico?

dimensione geografica fissa + istanze multiple è la soluzione più semplice. I ragazzi che lavorano su SWG hanno provato la dimensione dinamica e se ne sono pentiti.

Come gestire lo stato del gioco?

Il server è autorevole.

Come mantenere le cose sincronizzate?

Aggiornamenti periodici di sincronizzazione dal server. (non sono sicuro di quale sia la preoccupazione qui)

Come proteggere la comunicazione e il cliente dal reverse engineering?

Impossibile. assicurati solo di non fidarti di nulla che ricevi dal client e che il server sia autorevole.

Come aggirare i problemi di latenza?

Questo va a miglia di profondità, ma superficialmente si esegue la stessa simulazione sul client del server e quando si verifica la sincronizzazione, si risolvono le cose. Tutte le decisioni prese sul client vengono simulate anche sul server, quindi potrebbero esserci decisioni sbagliate, ma le cose generalmente funzionano.

Quali cose dovrebbero essere calcolate localmente e quali cose sul server?

Pensa al client come a eseguire una simulazione non autorevole di ciò che sta accadendo sul server. La reattività è la chiave dell'esperienza del giocatore, quindi devi fare qualcosa ogni volta che un giocatore prende una decisione, anche se sta solo iniziando una barra.

A dire il vero, molti di questi problemi sono ortogonali e possono essere applicate in seguito. Inizia a fare il gioco e non preoccuparti troppo di queste cose.


4

Questa domanda è molto ampia. È anche un'area molto difficile da padroneggiare, i programmatori di rete sono piuttosto ricercati nel settore con una retribuzione corrispondente, che indica che è un'area 'non risolta'. Ci sono libri là fuori, sì, molti. Ci sono buoni libri là fuori, senza dubbio. Ci sono libri là fuori che risponderanno alle tue domande? ... Non credo. Potrebbero avere soluzioni che funzionano in alcune situazioni o suggerimenti su cosa cercare, ma quasi tutte le tue domande dipendono dal gioco .... questa è un'area in cui dovrai davvero lavorare molto da solo, è così apparentemente banale e può andare storto in tanti modi (incontrollati).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.