Amazon GameLift ServersSuar ping UDP - Amazon GameLift Servers

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Amazon GameLift ServersSuar ping UDP

UDP ping beacon menyediakan cara untuk mengukur latensi jaringan antara perangkat pemain dan lokasi hosting. Amazon GameLift Servers Dengan ping beacon, Anda dapat mengumpulkan data latensi yang akurat untuk membuat keputusan berdasarkan informasi tentang penempatan server game dan meningkatkan perjodohan pemain berdasarkan persyaratan latensi.

Cara kerja ping beacon UDP

Amazon GameLift Serversmenyediakan endpoint UDP tetap (ping beacon) di setiap lokasi hosting tempat Anda dapat menyebarkan server game. Karena sebagian besar server game berkomunikasi menggunakan UDP, mengukur latensi dengan ping beacon UDP memberikan hasil yang lebih akurat daripada menggunakan ping ICMP. Perangkat jaringan sering menangani paket ICMP secara berbeda dari paket UDP, yang dapat menyebabkan pengukuran latensi yang tidak mencerminkan kinerja sebenarnya yang akan dialami pemain Anda.

Dengan suar ping UDP, klien game Anda dapat mengirim pesan UDP ke titik akhir ini dan menerima respons asinkron, memberi Anda pengukuran latensi yang lebih mewakili kondisi lalu lintas game aktual antara perangkat pemain dan lokasi hosting potensial. Titik akhir bersifat permanen dan tetap tersedia selama Amazon GameLift Servers mendukung hosting game di lokasi tersebut.

Kasus penggunaan umum untuk suar ping UDP

Anda dapat menggunakan ping beacon UDP dalam beberapa cara untuk mengoptimalkan pengalaman jaringan game Anda.

Memilih lokasi hosting yang optimal

Kumpulkan data latensi di berbagai wilayah geografis untuk mengidentifikasi lokasi utama dan cadangan terbaik untuk hosting server game untuk basis pemain Anda.

Menempatkan sesi permainan berdasarkan latensi pemain

Sertakan data latensi pemain saat meminta sesi permainan baru untuk membantu memilih lokasi yang memberikan pengalaman latensi terendah.

Mengoptimalkan perjodohan berdasarkan latensi

Berikan data latensi pemain saat meminta perjodohan untuk membantu mencocokkan pemain dengan profil latensi serupa dan menempatkan sesi permainan di lokasi optimal untuk pemain yang cocok.

catatan

Saat membuat permintaan perjodohan, Anda tidak boleh memberikan informasi latensi ke lokasi di mana Anda tidak memiliki armada. Jika Anda melakukannya, Amazon GameLift Servers mungkin mencoba menempatkan sesi permainan di lokasi di mana tidak ada kapasitas armada, yang mengakibatkan kegagalan permintaan perjodohan.

Mendapatkan titik akhir suar

Untuk mengambil domain ping beacon dan informasi port untuk Amazon GameLift Servers lokasi, gunakan operasi API. ListLocations Kumpulan lokasi yang dikembalikan oleh API ini bergantung pada yang Wilayah AWS Anda tentukan saat memanggilnya (atau Wilayah default jika Anda tidak menentukannya). Saat Anda menelepon dari:

  • Wilayah asal armada yang mendukung multi-lokasi: API mengembalikan informasi untuk semua lokasi hosting

  • Wilayah asal armada yang mendukung satu lokasi: API mengembalikan informasi untuk lokasi tersebut

Perhatikan bahwa jika Anda memanggil API ini menggunakan lokasi yang hanya dapat berupa lokasi jarak jauh dalam armada multi-lokasi, API akan menampilkan kesalahan karena jenis lokasi tersebut tidak memiliki titik akhir layanan.

Lihat tabel lokasi yang didukung AWS Lokasi yang didukung untuk mengidentifikasi Wilayah asal yang mendukung armada tunggal dan multi-lokasi.

Contoh

aws gamelift list-locations --region ap-northeast-2

Ini Wilayah AWS mendukung armada multi-lokasi, oleh karena itu beberapa lokasi akan dikembalikan. Berikut adalah contoh dari salah satu nilai yang dikembalikan:

[...] { "LocationName": "ap-northeast-1", "PingBeacon": { "UDPEndpoint": { "Domain": "gamelift-ping.ap-northeast-1.api.aws", "Port": 7770 } } }
penting

Cache informasi ping beacon daripada menelepon ListLocations sebelum setiap pengukuran latensi. Informasi domain dan port bersifat statis dan API tidak dirancang untuk permintaan volume tinggi.

Menerapkan pengukuran latensi

Ikuti praktik terbaik ini saat menerapkan pengukuran latensi menggunakan suar ping UDP:

  1. Simpan informasi ping beacon menggunakan salah satu pendekatan ini:

    • Hardcode titik akhir di klien game Anda.

    • Cache informasi di backend game Anda.

    • Menerapkan mekanisme pembaruan berkala (harian/mingguan) untuk menyegarkan informasi.

  2. Kirim pesan ping UDP:

    • Masukkan apa pun yang Anda inginkan di badan pesan, selama tidak kosong, dan Anda menyimpan pesan di bawah ukuran maksimum 300 byte.

    • Perhatikan batas tarif berikut untuk setiap lokasi:

      • 3 transaksi per detik (TPS) per alamat IP pengirim unik dan kombinasi port

      • 1000 TPS per alamat IP pengirim unik

  3. Hitung latensi:

    • Kirim beberapa ping ke setiap lokasi untuk menghitung latensi rata-rata.

    • Pertimbangkan untuk mengirim ping bersamaan ke beberapa lokasi untuk hasil yang lebih cepat.

    • Gunakan logika coba lagi sesuai kebutuhan untuk mengirim paket baru untuk paket apa pun yang tidak dikembalikan dalam waktu singkat (biasanya 1 - 3 detik), karena UDP tidak memiliki jaminan pengiriman 100%.

    • Hitung perbedaan waktu antara mengirim pesan dan menerima respons.

    • Jika sebagian besar ping UDP ke lokasi secara konsisten tidak mendapatkan respons kembali, hitung latensi menggunakan ping ICMP ke titik akhir Amazon GameLift Serverslayanan standar kami sebagai fallback.

Tip

Kami menyarankan Anda menyertakan port 7770 di mana pun Anda mendokumentasikan daftar port yang harus dibuka pemain Anda di jaringan lokal mereka. Ini adalah alasan lain mengapa Anda harus memiliki fallback untuk mengukur latensi (menggunakan ICMP, misalnya) jika port ini diblokir.

Contoh kode

Berikut adalah beberapa contoh sederhana yang menunjukkan cara mengirim ping UDP dan menghitung latensi.

C++
#include <iostream> #include <cstring> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> #include <chrono> int main() { // Replace with Amazon GameLift Servers UDP ping beacon domain for your desired location const char* domain = "gamelift-ping.ap-south-1.api.aws"; const int port = 7770; const char* message = "Ping"; // Your message const int num_pings = 3; // Number of pings to send // Create socket int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { std::cerr << "Error creating socket" << std::endl; return 1; } // Resolve domain name to IP address struct hostent* host = gethostbyname(domain); if (host == nullptr) { std::cerr << "Error resolving hostname" << std::endl; close(sock); return 1; } // Set up the server address structure struct sockaddr_in server_addr; std::memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); std::memcpy(&server_addr.sin_addr, host->h_addr, host->h_length); // Set socket timeout struct timeval tv; tv.tv_sec = 1; // 1 second timeout tv.tv_usec = 0; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { std::cerr << "Error setting socket timeout" << std::endl; close(sock); return 1; } double total_latency = 0; int successful_pings = 0; for (int i = 0; i < num_pings; ++i) { auto start = std::chrono::high_resolution_clock::now(); // Send the message ssize_t bytes_sent = sendto(sock, message, std::strlen(message), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)); if (bytes_sent < 0) { std::cerr << "Error sending message" << std::endl; continue; } // Receive response char buffer[1024]; socklen_t server_addr_len = sizeof(server_addr); ssize_t bytes_received = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&server_addr, &server_addr_len); auto end = std::chrono::high_resolution_clock::now(); if (bytes_received < 0) { std::cerr << "Error receiving response or timeout" << std::endl; } else { std::chrono::duration<double, std::milli> latency = end - start; total_latency += latency.count(); successful_pings++; std::cout << "Received response, latency: " << latency.count() << " ms" << std::endl; } // Wait a bit before next ping usleep(1000000); // 1s } // Close the socket close(sock); if (successful_pings > 0) { double avg_latency = total_latency / successful_pings; std::cout << "Average latency: " << avg_latency << " ms" << std::endl; } else { std::cout << "No successful pings" << std::endl; } return 0; }
C#
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Diagnostics; using System.Threading.Tasks; class UdpLatencyTest { static async Task Main() { // Replace with Amazon GameLift Servers UDP ping beacon domain for your desired location string domain = "gamelift-ping.ap-south-1.api.aws"; int port = 7770; string message = "Ping"; // Your message int numPings = 3; // Number of pings to send int timeoutMs = 1000; // Timeout in milliseconds await MeasureLatency(domain, port, message, numPings, timeoutMs); } static async Task MeasureLatency(string domain, int port, string message, int numPings, int timeoutMs) { using (var udpClient = new UdpClient()) { try { // Resolve domain name to IP address IPAddress[] addresses = await Dns.GetHostAddressesAsync(domain); if (addresses.Length == 0) { Console.WriteLine("Could not resolve domain name."); return; } IPEndPoint endPoint = new IPEndPoint(addresses[0], port); byte[] messageBytes = Encoding.UTF8.GetBytes(message); // Set receive timeout udpClient.Client.ReceiveTimeout = timeoutMs; double totalLatency = 0; int successfulPings = 0; var stopwatch = new Stopwatch(); for (int i = 0; i < numPings; i++) { try { stopwatch.Restart(); // Send message await udpClient.SendAsync(messageBytes, messageBytes.Length, endPoint); // Wait for response UdpReceiveResult result = await ReceiveWithTimeoutAsync(udpClient, timeoutMs); stopwatch.Stop(); double latency = stopwatch.Elapsed.TotalMilliseconds; totalLatency += latency; successfulPings++; string response = Encoding.UTF8.GetString(result.Buffer); Console.WriteLine($"Ping {i + 1}: {latency:F2}ms - Response: {response}"); } catch (SocketException ex) { Console.WriteLine($"Ping {i + 1}: Failed - {ex.Message}"); } catch (TimeoutException) { Console.WriteLine($"Ping {i + 1}: Timeout"); } // Wait before next ping await Task.Delay(1000); // 1s between pings } if (successfulPings > 0) { double averageLatency = totalLatency / successfulPings; Console.WriteLine($"\nSummary:"); Console.WriteLine($"Successful pings: {successfulPings}/{numPings}"); Console.WriteLine($"Average latency: {averageLatency:F2}ms"); } else { Console.WriteLine("\nNo successful pings"); } } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } } static async Task<UdpReceiveResult> ReceiveWithTimeoutAsync(UdpClient client, int timeoutMs) { using var cts = new System.Threading.CancellationTokenSource(timeoutMs); try { return await client.ReceiveAsync().WaitAsync(cts.Token); } catch (OperationCanceledException) { throw new TimeoutException("Receive operation timed out"); } } }
Python
import socket import time import statistics from datetime import datetime def udp_ping(host, port, timeout=2): """ Send a UDP ping and return the round trip time in milliseconds. Returns None if timeout occurs. """ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(timeout) message = b'ping' try: # Resolve hostname first try: socket.gethostbyname(host) except socket.gaierror as e: print(f"Could not resolve hostname: {e}") return None start_time = time.time() sock.sendto(message, (host, port)) # Wait for response data, server = sock.recvfrom(1024) end_time = time.time() # Calculate round trip time in milliseconds rtt = (end_time - start_time) * 1000 return rtt except socket.timeout: print(f"Request timed out") return None except Exception as e: print(f"Error: {type(e).__name__}: {e}") return None finally: sock.close() def main(): # Replace with Amazon GameLift Servers UDP ping beacon domain for your desired location host = "gamelift-ping.ap-south-1.api.aws" port = 7770 num_pings = 3 latencies = [] print(f"\nPinging {host}:{port} {num_pings} times...") print(f"Start time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") for i in range(num_pings): print(f"Ping {i+1}:") rtt = udp_ping(host, port) if rtt is not None: print(f"Response from {host}: time={rtt:.2f}ms") latencies.append(rtt) # Wait 1 second between pings if i < num_pings - 1: time.sleep(1) print() # Calculate and display statistics print("-" * 50) print(f"Ping statistics for {host}:") print(f" Packets: Sent = {num_pings}, Received = {len(latencies)}, " f"Lost = {num_pings - len(latencies)} " f"({((num_pings - len(latencies)) / num_pings * 100):.1f}% loss)") if latencies: print("\nRound-trip latency statistics:") print(f" Minimum = {min(latencies):.2f}ms") print(f" Maximum = {max(latencies):.2f}ms") print(f" Average = {statistics.mean(latencies):.2f}ms") print(f"\nEnd time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") if __name__ == "__main__": main()