Pengemasan data yang efisien untuk jaringan klien-server

8

Bahasa: C ++

Pertanyaan saya adalah sebagai berikut: Saya ingin tahu apa yang akan menjadi yang terbaik atau setidaknya cara yang baik untuk mengemas dan mengirim data dari klien ke server dan sebaliknya. Akan ada beberapa data yang menyusun satu paket. Sebuah paket akan memiliki "id", yang mendefinisikan untuk apa itu, kemudian data dalam urutan yang telah ditentukan untuk "tindakan" yang sesuai dengan paket tersebut.

Untuk sistem yang kurang bergantung pada kinerja, saya hanya akan mengirim string, yang akan dipisahkan oleh spasi, menjadi mereka data "aksi" dan "kata" pertama pengidentifikasi paket dan hanya rantai jika pernyataan memeriksa ketika ada kecocokan .

Sekarang untuk sistem yang lebih kritis, apa yang saya pikir sejauh ini adalah sesuatu seperti ini:

Buat string dengan id paket dan data, dan kirimkan. Kemudian, untuk membongkar, saya bisa mengekstrak integer pertama dalam string, dan dengan memiliki array penangan paket, dengan indeks yang sesuai dengan paket id yang mereka tangani, dan hanya melakukan sesuatu seperti packetHandlers [packetID] .Process (packageData).

Apa pendapat Anda tentang itu, ada saran? sangat dihargai!

Grimshaw
sumber

Jawaban:

10

Pertama, pastikan Anda benar-benar membutuhkan protokol yang mewah dan efisien sebelum membuang-buang sumber daya untuk mengembangkannya. Jangan lupa men-debug / memodifikasi game Anda akan lebih sulit dan memakan waktu karena protokol mewah Anda. Saya hanya akan abstrak komunikasi jaringan sehingga implementasi yang sebenarnya dapat dengan mudah ditukar dengan yang lebih efisien jika diperlukan di masa depan. Gunakan protokol sesederhana mungkin hingga Anda menemukan masalah kinerja. Keuntungan lain dari merancang protokol Anda nanti adalah protokol dapat dioptimalkan untuk data aktual yang diangkut vs apa yang Anda prediksi akan diangkut.

Setelah mengonfirmasi bahwa Anda memerlukan protokol mewah, lihat protokol yang telah banyak dikembangkan orang lain. Beberapa contoh:

  • (pembaruan) Pengembang asli Protokol Buffer (v2) mengembangkan protokol baru yang disebut Cap'n Proto. Ia menjelaskan keputusan desainnya dan membandingkannya dengan perpustakaan serupa lainnya yang baru saja dirilis: Cap'n Proto, FlatBuffers, dan SBE .
  • Hambatan utama Google adalah komunikasi jaringan antar komputer, sehingga mereka mungkin mempertimbangkan efisiensi ketika mengembangkan Protokol Buffer . Dengan anggun menangani kompatibilitas maju / mundur ( ketika Anda memutuskan untuk mengubah struktur data Anda). Digunakan oleh setiap produk Google utama (Gmail, Pencarian, dll)
  • Apache Thrift adalah protokol serupa yang digunakan oleh Facebook.
  • RakNet adalah perpustakaan jaringan open-source yang dirancang khusus untuk pengembangan game.
  • ZoidCom adalah perpustakaan jaringan lain yang diarahkan untuk pengembangan game. Ini bukan open-source, tetapi Anda masih bisa mempelajarinya untuk petunjuk desain.

Aturan Pertama Optimalisasi Program: Jangan lakukan itu.
Aturan Kedua Pengoptimalan Program (hanya untuk para ahli!): Jangan lakukan itu dulu.

[ Michael A. Jackson ]

Dengan kata lain: parameter optimasi utama Anda harus: hidup (tahun kehidupan per implementasi program). [ Cara Memprogram Game Independen. Slide 21. Jonathan Blow. ]

Leftium
sumber
1
pria membaca yang bagus! terima kasih banyak untuk jawaban yang lengkap, itu pasti membantu, dan saya mengikuti saran Anda sepenuhnya, hanya abstrak ini, membuatnya cukup sederhana untuk saat ini :)
Grimshaw
Cukup yakin bahwa Google use case untuk buffer protokol bukan efisiensi dalam arti standar, tetapi untuk memaksimalkan kompatibilitas antara semua platform yang mungkin dan versi data masa depan (yang merupakan efisiensi dalam cahaya lain). Saya akan ke sini membaca catatan Anda yang lain, koleksi yang sangat bagus bagi saya untuk berkenalan kembali dengan subjek.
Patrick Hughes
RakNet bukan open source.
Gerstmann
@Gerstmann: Raknet adalah open source (sekali lagi): github.com/OculusVR/RakNet
Leftium
0

Mengapa menggunakan dua skema pengkodean yang berbeda? Cukup gunakan yang kedua untuk setiap sistem. Sederhana saja.
Pertimbangkan untuk menggunakan kompresi delta. Yaitu mengirim satu nilai penuh dan setelah itu hanya hal-hal yang berubah. Setelah beberapa iterasi permainan mengirim nilai penuh lagi.
Encodig lain yang dapat Anda pertimbangkan adalah Base 128 Varint. Google Protobuf menggunakannya. Lihatlah halaman "Pengkodean" dari panduan pengembang mereka: Pengodean Protokol Buffer dapat menghemat beberapa byte.

Lurca
sumber
Sistem pertama yang saya bicarakan hanyalah contoh dari proyek lain :) Saya tentu saja menikmati ide kompresi delta, terima kasih sobat!
Grimshaw
0

Apa yang mungkin menjadi contoh dari data yang Anda kirim? Saya tidak melihat alasan untuk melakukan sesuatu yang terlalu mewah. Setelah data dimuat penuh ke buffer penerima, periksa duluint berdasarkan nilainya, Anda kemudian tahu bagaimana memproses sisa data.

Jadi paket yang memiliki empat bagian Data id, val1, val2, dan val2mungkin terlihat seperti ini:

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

Saat Anda membaca byte pertama (yang Anda tahu akan selalu ada di sana) Anda memutuskan bagaimana memproses set data berikutnya. Jika kata pertama (id) adalah 00000001Anda tahu ada tiga kata lagi yang mengikuti, dan itu adalah akhir dari paket. Untuk melanjutkan contoh, Anda mungkin memiliki id = 00000010dan spesifikasi Anda memberitahu Anda bahwa untuk nilai id 2, Anda proses float, float,float agar, yang mungkin menentukan posisi pemain di ruang dunia.

Anggap itu sebagai menulis sistem file biner Anda sendiri, Anda memiliki nilai header, yang menggambarkan sisa data, di mana ia berada (posisi apa) dan apa jenis data untuk memperlakukannya.

Nate
sumber
Mengerti, satu-satunya pertanyaan saya tetap adalah: apakah mengemas semua int dan mengapung dalam string standar cukup, atau haruskah saya pergi dengan tipe data yang lebih ringan?
Grimshaw
Seperti yang dikatakan oleh orang lain, mulailah dengan string dan lihat apa yang terjadi. Kemungkinannya, Anda akan memiliki leher botol di tempat lain dalam kode Anda.
Nate