Ini adalah kumpulan informasi yang saya butuhkan untuk mengimplementasikan tahap membangun koneksi antara peserta dalam permainan jaringan peer-to-peer menggunakan protokol UDP.
Artikel ini dirancang untuk pengembang game pemula. Saya mencoba menulis artikel yang saya sendiri ingin baca pada saat saya baru mulai memahami topik ini: sehingga semua nuansa yang diperlukan dikumpulkan di satu tempat, tetapi pada saat yang sama tidak ada yang berlebihan, dalam bahasa yang sederhana, dan dengan gambar visual. Mungkin seseorang akan berguna.
Pengembang game berpengalaman tidak mungkin menemukan sesuatu yang baru untuk mereka sendiri di sini. Tapi saya akan berterima kasih atas komentar dan komentarnya.
Game jaringan dengan arsitektur peer-to-peer
- Setiap pemain menyimpan seluruh keadaan dunia game dan memprosesnya secara serempak dengan pemain lain. Setiap pemain memberikan aksi pengguna ke semua pemain lain. Pemain utama yang mengumpulkan pemain lain disebut server dan sisanya adalah klien. Server adalah yang utama hanya pada tahap pengumpulan pemain. Dan selama pertandingan tidak ada komputer utama.
- Pendekatan ini memiliki beberapa fitur berikut:
- Lalu lintas tidak tergantung pada kompleksitas dunia game, tetapi hanya pada jumlah pemain. Dalam mode ini, strategi real-time biasanya berfungsi, di mana Anda perlu memproses ribuan unit.
- Volume lalu lintas adalah urutan N², di mana N adalah jumlah pemain. Karenanya, pendekatan ini hanya berlaku untuk game dengan jumlah pemain yang sedikit.
- Karena data ditransmisikan secara langsung antara pemain tanpa server perantara, penundaan transmisi (kelambatan) minimal. Tetapi jika setidaknya salah satu pemain memiliki masalah komunikasi, maka ini akan mempengaruhi semua pemain.
- Penting untuk membuat saluran komunikasi antara semua pemain. Tetapi jika para pemain berada di jaringan lokal yang berbeda, maka ini tidak selalu memungkinkan.
- Anda bisa menggunakan TCP atau UDP untuk mentransfer data dalam game.
- TCP (Transmission Control Protocol) menyediakan pengiriman byte stream yang andal. Ini menyederhanakan implementasi game, tetapi tidak ada kontrol atas keterlambatan pengiriman data.
- UDP (User Datagram Protocol) adalah protokol transfer paket sederhana tanpa jaminan pengirimannya. Tetapi karena kesederhanaannya, UDP digunakan dalam sistem waktu nyata ketika tidak dapat diterima untuk menunggu paket yang tertunda atau hilang. Menggunakan UDP dapat mengurangi penundaan dalam game, tetapi mempersulit implementasi game.
Artikel ini menjelaskan penggunaan UDP.
Membuat koneksi di jaringan lokal
- Untuk membuat koneksi antara pemain, klien perlu mengetahui alamat IP server dan port yang didengarkan oleh program game.
- Misalnya, komputer pemain A memiliki alamat IP 192.168.1.2 di jaringan lokal. Player A meluncurkan program game di komputernya dalam mode server, dan program mendengarkan port 50120. Player A entah bagaimana mengkomunikasikan informasi ini ke pemain B.
- Komputer Player B memiliki alamat IP 192.168.1.5 di jaringan lokal. Player B meluncurkan program game di komputernya dalam mode klien, dan program tersebut menempati port 50150. Player B memasuki alamat server 192.168.1.2►0120 dalam program game, dan program mengirimkan permintaan ke server di alamat yang ditentukan.
- Server dalam mode siaga, dan setelah menerima permintaan dari pemain B, ia akan mengetahui alamatnya 192.168.1.5►0150. Dengan demikian, klien dan server membuat koneksi dan dapat memulai permainan.
- Jika beberapa klien terhubung ke server, maka server harus mengirim masing-masing alamat klien lain.
Dalam contoh di gambar, server A mengirim klien B alamat klien C (192.168.1.6►0160), dan klien C mengirim alamat klien B (192.168.1.5►0150). Dengan demikian, semua pemain akan dapat membangun koneksi "masing-masing dengan masing-masing."
- Setiap kali gim dimulai, server dapat meminta port gratis dari sistem operasi. Tetapi lebih nyaman menggunakan port yang sama setiap kali sehingga klien tidak harus memasukkan port baru setiap waktu.
Semua port dibagi menjadi tiga rentang:
- [0, 1023] - terkenal (sistemik).
- [1024, 49151] - terdaftar (pengguna). Port untuk server harus dipilih dalam kisaran ini.
- [49152, 65535] - dinamis (pribadi). Di sini, OS mengalokasikan port sementara untuk program.
Di Wikipedia, Anda dapat melihat daftar port yang dipesan . Selanjutnya, misalnya, port 49094 untuk server permainan dipilih.
- Komputer dapat memiliki beberapa antarmuka jaringan, baik nyata (Ethernet, WiFi), dan virtual (VPN). Setiap antarmuka jaringan memiliki alamat IP sendiri. Program ini dapat memberi pengguna server peluang untuk memilih antarmuka jaringan yang dengannya ia akan menunggu permintaan klien. Tetapi nyaman untuk menggunakan alamat IP wildcard khusus 0.0.0.0 . Jika program membuka soket dengan alamat IP ini, maka ia akan mendengarkan port yang ditentukan untuk semua antarmuka jaringan komputer ini. Dengan demikian, pemain tidak harus memikirkan antarmuka jaringan mana yang harus dipilih.
- Anda juga dapat membantu klien dan secara otomatis menentukan alamat IP server. Jika klien mengirim permintaan ke alamat IP broadcast khusus (broadcast) , maka semua komputer di jaringan lokal akan menerimanya.
Misalnya, jika alamat jaringan 192.168.1.0, subnet mask adalah 255.255.255.0, maka alamat IP broadcast akan menjadi 192.168.1.255.
Jika semua server game mendengarkan pada port 49094, maka paket yang dikirim ke alamat 192.168.1.255-00-009094 akan diterima oleh semua server game di jaringan ini. Setiap server akan mengirimkan konfirmasi kepada pengirim. Dan klien akan menerima daftar semua server game di jaringannya, dan akan dapat memilih server yang dia butuhkan.
- Jika semua pemain berada di jaringan lokal yang sama, maka membangun koneksi "masing-masing dengan masing-masing" cukup sederhana. Mungkin ada masalah dengan akses klien ke port server karena Firewall. Tapi itu tergantung pada pengaturan OS dan keamanan.
Membuat koneksi dari jaringan lokal ke server di Internet
- Sebagai aturan, komputer tidak terhubung ke Internet secara langsung, tetapi melalui router. Dan, sebagai aturannya, router melakukan terjemahan alamat jaringan (NAT, Terjemahan Alamat Jaringan) .
Sebagai contoh, klien C berada di jaringan lokal dan memiliki akses ke Internet melalui router B, sementara server A memiliki alamat IP publik di Internet. Biarkan mereka memiliki alamat berikut:

- Alamat Internet Server A adalah 203.0.113.2. Program server mendengarkan pada port 49094.
- Alamat router B di Internet adalah 203.0.113.5. Alamat router B di jaringan lokal adalah 192.168.1.1.
- Alamat C klien di jaringan lokal adalah 192.168.1.5. Program klien menempati port 50150, dan mengirim paket ke server di 203.0.113.2-00-009094.
- Router B adalah gateway default di jaringan lokalnya. Yaitu, semua paket dengan alamat yang bukan dari jaringan lokal saat ini dikirim ke sana.
- Router memiliki tabel terjemahan alamat: (alamat internal: port internal) - (alamat eksternal: port eksternal). Setelah menerima paket dari klien ke server 203.0.113.2-00-009094, router memilih port eksternal gratis, misalnya 52050, dan membuat entri dalam tabel terjemahan alamat: 192.168.1.5►0150 - 203.0.113.5►2050.
- Router mengganti alamat internal pengirim 192.168.1.5/100150 dalam paket dengan alamat eksternal 203.0.113.5/102050, dan mentransfer paket yang diubah ke server.
- Server menerima paket dengan alamat pengirim 203.0.113.5► 2020, dan mengirim respons ke alamat ini, yaitu ke router.
- Setelah menerima paket dari server, router mencari alamat penerima di tabel terjemahan alamatnya, melakukan penggantian terbalik alamat eksternal penerima 203.0.113.5►2050 dengan alamat internal 192.168.1.5►0150, dan mengirimkan paket ke alamat ini, yaitu klien.
- Jika klien mengirim paket berikutnya ke server, router melihat alamat pengirim untuk melihat apakah entri seperti itu sudah ada dalam tabel, dan jika demikian, ia menggunakan port eksternal yang sebelumnya dialokasikan, dalam hal ini 52050.
- Dengan demikian, klien dan server membuat koneksi melalui NAT, dan dapat memulai permainan. Tetapi server tidak mengetahui alamat internal klien di jaringan lokalnya, dan menganggap bahwa klien adalah router.
- Entri dalam tabel terjemahan alamat berlaku untuk jangka waktu tertentu, biasanya 1-3 menit. Oleh karena itu, klien dan server perlu bertukar paket secara berkala sehingga catatan yang menghubungkannya tidak dihapus. Jika klien mengirim paket baru ke server setelah menghapus catatan, maka port eksternal yang berbeda dapat dialokasikan untuk catatan baru di router, dan untuk server itu akan menjadi klien lain dengan alamat yang berbeda.
- Sebagai aturan, router pengguna tidak terhubung langsung ke Internet, tetapi terletak di jaringan internal penyedia Internet. Artinya, klien berada di belakang dua NAT.
Misalnya, seperti ini:
Yaitu, terjemahan ganda dari alamat jaringan dilakukan.
- Ada berbagai jenis NAT:
- NAT kerucut penuh
- Setelah entri dibuat dalam tabel terjemahan alamat (alamat internal: port internal) - (alamat eksternal: port eksternal), semua paket dari pengirim (alamat internal: port internal) ditransmisikan melalui (alamat eksternal: port eksternal) ke alamat penerima.
- Setiap server eksternal dapat mengirim paket ke (alamat internal: port internal), mengirim paket ke (alamat eksternal: port eksternal).
Sebagai contoh, klien C mengirimkan paket ke server A dan D menggunakan alamat eksternal yang sama 203.0.113.5► 202050. Jika server E mengirim paket ke alamat ini 203.0.113.5► 202050, router akan meneruskannya ke klien C.
- Alamat-cone NAT.
- Setelah entri dibuat dalam tabel terjemahan alamat (alamat internal: port internal) - (alamat eksternal: port eksternal), semua paket dari pengirim (alamat internal: port internal) ditransmisikan melalui (alamat eksternal: port eksternal) ke alamat penerima.
- Server eksternal (alamat server: port server) dapat mengirim paket ke (alamat internal: port internal), mengirim paket ke (alamat eksternal: port eksternal) hanya jika (alamat internal: port internal) yang sebelumnya mengirim paket ke (alamat server: apa saja porta).
Sebagai contoh, klien C mengirimkan paket ke server A dan D menggunakan alamat eksternal yang sama 203.0.113.5► 202050. Server D dapat mengirim paket ke klien C melalui alamat router 203.0.113.5► 202050 dari salah satu port-nya. Tetapi router tidak akan melewatkan paket dari server E.
- NAT kerucut yang dibatasi port.
- Setelah entri dibuat dalam tabel terjemahan alamat (alamat internal: port internal) - (alamat eksternal: port eksternal), semua paket dari pengirim (alamat internal: port internal) ditransmisikan melalui (alamat eksternal: port eksternal) ke alamat penerima.
- Server eksternal (alamat server: port server) dapat mengirim paket ke (alamat internal: port internal), mengirim paket ke (alamat eksternal: port eksternal) hanya jika (alamat internal: port internal) yang sebelumnya mengirim paket ke (alamat server: port server).
Sebagai contoh, klien C mengirimkan paket ke server A dan D menggunakan alamat eksternal yang sama 203.0.113.5► 202050. Router tidak akan melewatkan paket dari server E atau port server D.
- Symmetric NAT (Symmetric NAT).
- Jika pengirim internal yang sama (alamat internal: port internal) mengirimkan paket ke penerima yang berbeda (alamat server: port server), maka port eksternal yang terpisah akan dialokasikan untuk setiap alamat penerima dan entri yang terpisah akan digunakan dalam tabel terjemahan alamat.
- Hanya server eksternal (alamat server: port server) yang menerima paket dari pengirim internal (alamat internal: port internal) yang dapat mengirim paket kembali.
Sebagai contoh, klien C mengirim paket ke server A menggunakan alamat eksternal 203.0.113.5► 202050, dan ke server D menggunakan alamat eksternal lain 203.0.113.5. 20201. Router tidak akan melewatkan paket dari server E atau port server D.
- Jika beberapa klien terhubung ke server game, maka untuk game peer-to-peer Anda perlu membuat koneksi langsung antara setiap pasangan klien yang melewati server.
Misalnya, dua klien C dan E yang terhubung ke server A:

- Klien C memiliki alamat internal 192.168.1.5/100150 dan alamat eksternal 203.0.113.5/102050.
- Klien E memiliki alamat internal 192.168.2.5:50250 dan alamat eksternal 203.0.113.6-062060.
- Server harus memberi tahu setiap klien alamat eksternal dari klien lain.
- Biasanya, router menggunakan NAT jenis NAT kerucut yang dibatasi Port. Router meneruskan paket ke klien hanya dari pengirim (alamat IP dan port) ke mana klien mengirim paket sebelumnya. Dan jika klien C mengirim paket ke klien E, maka router D tidak akan melewatkan paket ini.
- Dalam hal ini, metode meninju lubang UDP digunakan. Kedua klien harus saling mengirim paket UDP. Segera setelah klien C mengirim paket ke klien E, maka router B akan siap menerima paket dari klien E. Demikian pula, begitu klien E mengirim paket ke klien C, maka router D akan siap menerima paket dari klien C. Paket pertama dari klien yang memulai mengirimkan pertama akan hilang. Tetapi begitu klien kedua juga mulai mengirim paket ke arah, kedua klien akan dapat bertukar paket.
- Tetapi jika router menggunakan Symmetric NAT, port eksternal baru akan dialokasikan untuk setiap penerima. Dan, sebagai aturan, tidak ada cara untuk mengetahui port mana yang telah dialokasikan oleh router. Oleh karena itu, jika setidaknya salah satu router menggunakan Symmetric NAT, tidak mungkin untuk membuat koneksi antara klien.
- Jika dua klien berada di jaringan lokal yang sama, maka mereka hanya akan tahu alamat eksternal masing-masing.
Sebagai contoh, klien C mengirim paket ke klien D di alamat eksternal 203.0.113.5Point2051. Router B harus memproses paket ini seolah-olah diterima dari jaringan eksternal, ganti alamat penerima 203.0.113.5► 20201 dengan alamat internal klien D 192.168.1.6►006060, dan kirim paket ke klien D kembali ke jaringan lokal. Fungsi router ini disebut NAT loopback ( NAT hairpinning ). Jika NAT loopback dinonaktifkan pada router, maka tidak mungkin untuk membuat koneksi antara klien.
- Klien dapat berlokasi di jaringan lokal yang berbeda, tetapi memiliki akses ke Internet melalui penyedia Internet umum.
Jika NAT loopback dimatikan pada peralatan penyedia layanan Internet, maka tidak mungkin untuk membuat koneksi antara klien.
- Apa yang harus saya lakukan jika Symmetric NAT digunakan pada router, atau NAT loopback dimatikan?
Seperti yang saya pahami, satu-satunya cara yang dapat diandalkan untuk memecahkan masalah ini adalah dengan mentransfer paket tidak langsung antara klien, tetapi melalui server. Penting untuk mengimplementasikan fungsi ini dalam program game dalam kerangka arsitektur peer-to-peer, atau untuk mengimplementasikan arsitektur client-server.
Atau Anda dapat menggunakan program pihak ketiga untuk membuat VPN, misalnya LogMeIn Hamachi .
Membuat koneksi antar LAN di Internet
- Sebagai aturan, tidak ada pemain yang memiliki alamat IP publik, dan para pemainnya berada di jaringan lokal yang berbeda di belakang NAT.
Misalnya, dalam skema ini, klien C akan mengirim paket ke server A di alamat eksternal 203.0.113.2-022020, di mana port dipilih oleh router B. Oleh karena itu, memilih port internal server A tidak masalah, dan Anda dapat memilih port apa saja. Dalam hal ini, alih-alih port 49094, server A dapat meminta port gratis dari OS, misalnya 50120.
- Agar server A dan klien C membuat koneksi, pertama-tama, masing-masing dari mereka perlu mencari tahu alamat eksternalnya.
Anda dapat menggunakan protokol STUN (Session Traversal Utilities for NAT) untuk ini .
Protokol STUN memungkinkan klien yang berada di belakang NAT untuk menentukan alamat dan port IP eksternal.
Pesan STUN dikirim dalam paket UDP.
Klien dapat mengakses server STUN publik mana saja. Daftar server STUN publik dapat ditemukan di Wikipedia . Atau cari "daftar server STUN publik" .
Metode ini tidak berlaku jika setidaknya salah satu pemain di router menggunakan "Symmetric NAT".
- Setelah masing-masing pemain mempelajari alamat eksternalnya, ia harus entah bagaimana memberikan alamatnya kepada semua pemain lain.
Agar pemain dapat bertukar alamat, Anda dapat menggunakan server publik Anda. Dalam diagram, ini disebut server alamat.
Ini tidak selalu memerlukan server khusus. Anda dapat menggunakan hosting apa pun dengan server web dan dengan dukungan bahasa scripting apa pun, seperti PHP. Menggunakan protokol HTTP, setiap pemain harus mengirim alamat eksternal mereka ke server alamat. Dan kemudian minta alamat semua pemain lain.
- Misalnya, setiap server game dapat mendaftarkan pengidentifikasi uniknya (game-id) di server alamat. Anda dapat menggunakan string apa pun sebagai id permainan, misalnya, nama panggilan (alias) dari pengguna server. Pengguna server entah bagaimana memberitahu id permainan kepada para pemain yang ingin ia undang ke gimnya. Dan para pemain ini akan dapat bergabung dengan game dengan meminta id-game dari server alamat alamat eksternal semua peserta dalam game ini.
- Setelah masing-masing pemain menerima alamat eksternal semua pemain lain, mereka dapat membangun koneksi satu-ke-masing-masing menggunakan metode meninju lubang UDP .