Amazon GameLift ServersUDP-Ping-Beacons - Amazon GameLift Servers

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Amazon GameLift ServersUDP-Ping-Beacons

UDP-Ping-Beacons bieten eine Möglichkeit, die Netzwerklatenz zwischen Player-Geräten und Amazon GameLift Servers Hosting-Standorten zu messen. Mit Ping-Beacons können Sie genaue Latenzdaten sammeln, um fundierte Entscheidungen über die Platzierung von Spieleservern zu treffen und die Spielersuche auf der Grundlage der Latenzanforderungen zu verbessern.

Wie funktionieren UDP-Ping-Beacons

Amazon GameLift Serversbietet feste UDP-Endpunkte (Ping-Beacons) an jedem Hosting-Standort, an dem Sie Spieleserver bereitstellen können. Da die meisten Spieleserver über UDP kommunizieren, liefert die Messung der Latenz mit UDP-Ping-Beacons genauere Ergebnisse als die Verwendung von ICMP-Pings. Netzwerkgeräte verarbeiten ICMP-Pakete oft anders als UDP-Pakete, was zu Latenzmessungen führen kann, die nicht die tatsächliche Leistung widerspiegeln, die Ihre Spieler erleben werden.

Mit UDP-Ping-Beacons kann dein Spielclient UDP-Nachrichten an diese Endpunkte senden und asynchrone Antworten empfangen. So erhältst du Latenzmessungen, die die tatsächlichen Verkehrsbedingungen im Spiel zwischen dem Gerät eines Spielers und potenziellen Hosting-Standorten besser wiedergeben. Die Endpunkte sind permanent und bleiben verfügbar, solange das Hosten von Spielen an diesem Amazon GameLift Servers Standort unterstützt wird.

Häufige Anwendungsfälle für UDP-Ping-Beacons

Du kannst UDP-Ping-Beacons auf verschiedene Arten verwenden, um das Netzwerkerlebnis deines Spiels zu optimieren.

Auswahl optimaler Hosting-Standorte

Erfassen Sie Latenzdaten aus verschiedenen geografischen Regionen, um die besten Primär- und Backup-Standorte für das Hosten von Spieleservern für Ihre Spielerbasis zu ermitteln.

Platzieren von Spielsitzungen auf der Grundlage der Spielerlatenz

Füge Daten zur Spielerlatenz hinzu, wenn du neue Spielsitzungen anforderst, damit du Orte auswählen kannst, die die niedrigste Latenz bieten.

Optimieren Sie das Matchmaking auf der Grundlage der Latenz

Geben Sie Daten zur Spielerlatenz an, wenn Sie Matchmaking anfragen, um Spielern mit ähnlichen Latenzprofilen zu helfen und Spielsitzungen an optimalen Orten für passende Spieler zu platzieren.

Anmerkung

Wenn du Anfragen zur Spielerzuweisung erstellst, solltest du keine Latenzinformationen an Standorte weitergeben, an denen du keine Flotten hast. Wenn ihr das tut, versucht Amazon GameLift Servers vielleicht, die Spielsitzung an Orten zu platzieren, an denen es keine Flottenkapazität gibt, was dazu führen kann, dass Spielerzuweisungsanfragen fehlschlagen.

Beacon-Endpunkte abrufen

Verwenden Sie den API-Vorgang, um Domänen- und Portinformationen für Ping-Beacons für Amazon GameLift Servers Standorte abzurufen. ListLocations Welche Speicherorte von dieser API zurückgegeben werden, hängt von den Speicherorten ab, die AWS-Region Sie beim Aufrufen der API angegeben haben (oder von Ihrer Standardregion, falls Sie keine angeben). Wenn Sie anrufen von:

  • Eine Heimatregion einer Flotte, die mehrere Standorte unterstützt: Die API gibt Informationen für alle Hosting-Standorte zurück

  • Eine Heimatregion einer Flotte, die einen einzelnen Standort unterstützt: Die API gibt Informationen für diesen Standort zurück

Beachten Sie, dass die API einen Fehler zurückgibt, wenn Sie diese API über einen Standort aufrufen, der nur ein entfernter Standort in einer Flotte mit mehreren Standorten sein kann, da diese Art von Standort keinen Service-Endpunkt hat.

In der Tabelle der unterstützten Standorte finden Sie die HeimatregionenUnterstützte AWS Standorte, in denen Flotten mit einem oder mehreren Standorten unterstützt werden.

Beispiel

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

Dies AWS-Region unterstützt Flotten mit mehreren Standorten, weshalb mehrere Standorte zurückgegeben werden. Hier ist ein Beispiel für einen der Rückgabewerte:

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

Zwischenspeichern Sie die Ping-Beacon-Informationen, anstatt ListLocations sie vor jeder Latenzmessung aufzurufen. Die Domain- und Portinformationen sind statisch und die API ist nicht für Anfragen mit hohem Volumen konzipiert.

Implementierung von Latenzmessungen

Beachten Sie bei der Implementierung von Latenzmessungen mithilfe von UDP-Ping-Beacons die folgenden bewährten Methoden:

  1. Speichern Sie Ping-Beacon-Informationen mit einem der folgenden Ansätze:

    • Kodieren Sie die Endpunkte in Ihrem Spielclient fest.

    • Zwischenspeichern Sie die Informationen in Ihrem Spiel-Backend.

    • Implementieren Sie einen Mechanismus zur regelmäßigen Aktualisierung (täglich/wöchentlich), um die Informationen zu aktualisieren.

  2. Senden Sie UDP-Ping-Nachrichten:

    • Fügen Sie in den Nachrichtentext ein, was Sie wollen, solange er nicht leer ist und Sie Nachrichten unter der maximalen Größe von 300 Byte halten.

    • Beachten Sie für jeden Standort die folgenden Ratenbegrenzungen:

      • 3 Transaktionen pro Sekunde (TPS) pro eindeutiger Kombination aus IP-Adresse und Port des Absenders

      • 1000 TPS pro eindeutiger Absender-IP-Adresse

  3. Latenz berechnen:

    • Senden Sie mehrere Pings an jeden Standort, um die durchschnittliche Latenz zu berechnen.

    • Erwägen Sie, gleichzeitige Pings an mehrere Standorte zu senden, um schnellere Ergebnisse zu erzielen.

    • Verwenden Sie bei Bedarf die Wiederholungslogik, um neue Pakete für jedes Paket zu senden, das nicht innerhalb kurzer Zeit (normalerweise 1—3 Sekunden) zurückgegeben wurde, da bei UDP die Zustellung nicht zu 100% garantiert ist.

    • Berechnet den Zeitunterschied zwischen dem Senden einer Nachricht und dem Empfangen der Antwort.

    • Wenn ein großer Teil der UDP-Pings an einen Standort konsistent keine Antwort erhält, berechnen Sie die Latenz, indem Sie ICMP-Pings zu unseren Amazon GameLift ServersStandarddienstendpunkten als Fallback verwenden.

Tipp

Wir empfehlen, dass Sie Port 7770 überall dort angeben, wo Sie die Liste der Ports dokumentieren, die Ihre Player in ihrem lokalen Netzwerk geöffnet haben müssen. Dies ist ein weiterer Grund, warum Sie einen Fallback zur Messung der Latenz (z. B. mit ICMP) haben sollten, falls dieser Port blockiert ist.

Codebeispiele

Hier sind einige einfache Beispiele, die zeigen, wie man UDP-Pings sendet und die Latenz berechnet.

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()