Imballaggio efficiente dei dati per una rete client-server


8

Lingua: C ++

La mia domanda è la seguente: vorrei sapere quale sarebbe il migliore o almeno un buon modo per impacchettare e inviare dati dal client al server e viceversa. Ci saranno alcuni dati che compongono un singolo pacchetto. Un pacchetto avrà un "id", che definisce a cosa serve, quindi i dati in un ordine predeterminato per quella "azione" cui corrisponde il pacchetto.

Per sistemi meno dipendenti dalle prestazioni, invierei semplicemente stringhe, che sarebbero separate da uno spazio, essendo loro i dati dell '"azione" e la prima "parola" l'identificatore del pacchetto e solo la catena se le istruzioni controllano quando c'è una corrispondenza .

Ora per un sistema più critico, quello che ho pensato finora era qualcosa del genere:

Crea una stringa con ID pacchetto e dati e inviala. Quindi, per decomprimere, ho potuto estrarre il primo intero nella stringa e avendo una matrice di gestori di pacchetti, con indici corrispondenti all'ID pacchetto che gestiscono, e fare semplicemente qualcosa come packetHandlers [packetID] .Process (packetData).

Cosa ne pensi, qualche suggerimento? molto apprezzato!

Risposte:


10

Innanzitutto, conferma di aver effettivamente bisogno di un protocollo elegante ed efficiente prima di sprecare risorse per svilupparlo. Non dimenticare il debug / modifica del gioco sarà più difficile e dispendioso in termini di tempo a causa del tuo protocollo sofisticato. Vorrei solo sottrarre la comunicazione di rete in modo che l'implementazione effettiva possa essere facilmente sostituita con una più efficiente se necessario in futuro. Utilizzare il protocollo più semplice possibile fino a quando non si verificano problemi di prestazioni. Un altro vantaggio della progettazione del protocollo in un secondo momento è che il protocollo può essere ottimizzato per i dati effettivi trasportati rispetto a ciò che si prevede sarà trasportato.

Dopo aver confermato che hai bisogno di un protocollo elaborato, osserva i protocolli che altri hanno trascorso molto tempo a sviluppare. Qualche esempio:

  • (aggiornamento) Lo sviluppatore originale di Protocol Buffers (v2) ha sviluppato un nuovo protocollo chiamato Cap'n Proto. Spiega le sue decisioni di progettazione e confronta con altre librerie simili che sono state recentemente rilasciate: Cap'n Proto, FlatBuffers e SBE .
  • Il principale collo di bottiglia di Google è la comunicazione di rete tra computer, quindi probabilmente hanno considerato l'efficienza nello sviluppo di Protocollo Buffer . Gestisce con grazia la compatibilità avanti / indietro ( quando si decide di modificare le strutture dei dati). Utilizzato da tutti i principali prodotti Google (Gmail, Ricerca, ecc.)
  • Apache Thrift è un protocollo simile utilizzato da Facebook.
  • RakNet è una libreria di rete open source appositamente progettata per lo sviluppo di giochi.
  • ZoidCom è un'altra libreria di rete orientata allo sviluppo di giochi. Non è open-source, ma puoi ancora studiarlo per suggerimenti di progettazione.

La prima regola di ottimizzazione del programma: non farlo.
La seconda regola di ottimizzazione del programma (solo per esperti!): Non farlo ancora.

[ Michael A. Jackson ]

In altre parole: il parametro di ottimizzazione principale dovrebbe essere: vita (anni di vita per implementazione del programma). [ Come programmare giochi indipendenti. Slide 21. Jonathan Blow. ]


1
bella lettura amico! grazie mille per la risposta completa, mi ha sicuramente aiutato, e sto seguendo interamente i tuoi consigli, riassumilo, rendendolo abbastanza semplice per ora :)
Grimshaw

Abbastanza sicuro che il caso d'uso di Google per i buffer di protocollo non fosse efficienza in senso standard, ma per massimizzare la compatibilità tra tutte le piattaforme possibili e tutte le versioni future dei dati (che è efficienza sotto un'altra luce). Sarò qui a leggere le tue altre note, una collezione molto bella per me per farmi conoscere nuovamente l'argomento.
Patrick Hughes,

RakNet non è open source.
Gerstmann,

@Gerstmann: Raknet è open source (ancora una volta): github.com/OculusVR/RakNet
Leftium

0

Perché usare due diversi schemi di codifica? Basta usare il secondo per ogni sistema. Mantienilo semplice.
Prendi in considerazione l'utilizzo della compressione delta. Vale a dire inviare un valore completo e successivamente solo le cose che sono cambiate. Dopo alcune iterazioni di gioco, invia nuovamente un valore completo.
Un'altra codifica che potresti prendere in considerazione è Base 128 Varint. Google Protobuf lo usa. Dai un'occhiata alla pagina "Codifica" della loro guida per sviluppatori: Codifica buffer buffer Potrebbe salvare qualche byte.


Il primo sistema di cui ho parlato è stato un semplice esempio di un altro progetto :) Ho sicuramente apprezzato l'idea di compressione delta, grazie amico!
Grimshaw,

0

Quale potrebbe essere un esempio dei dati che stai inviando? Non vedo alcun motivo per fare qualcosa di eccessivamente elaborato. Una volta che i dati sono stati caricati completamente nel buffer del ricevitore, ispezionare il primo in intbase al suo valore, quindi si sa come elaborare il resto dei dati.

Quindi un pacchetto che ha quattro parti di dati id, val1, val2, e val2potrebbe essere simile a questo:

// I'm using words (one byte) so my sample data is short
00000001 00101000 00010110 00010100 

Mentre leggi il primo byte (che sai sarà sempre lì) decidi come elaborare il prossimo set di dati. Se la prima parola (id) è 00000001a conoscenza, ci sono altre tre parole che seguono, e questa è la fine del pacchetto. Per continuare l'esempio, si potrebbe avere id = 00000010e le specifiche si dice che per il valore id 2, si elabora float, float, floatin questo ordine, che potrebbe specificare una posizione del giocatore nello spazio mondo.

Pensa a come scrivere il tuo file system binario, hai un valore di intestazione, che descrive il resto dei dati, dove si trova (quale posizione) e che tipo di dati per trattarlo.


Capito, l'unica domanda che rimango è: impacchettare tutti quegli interi e float in una stringa standard abbastanza, o dovrei scegliere tipi di dati più leggeri?
Grimshaw,

Come detto da altri, inizia con la stringa e guarda cosa succede. È probabile che avrai un collo di bottiglia altrove nel tuo codice.
Nate,
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.