Amazon GameLift ServersBalizas de ping UDP - Amazon GameLift Servers

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Amazon GameLift ServersBalizas de ping UDP

Las balizas de ping UDP proporcionan una forma de medir la latencia de la red entre los dispositivos de los jugadores y las ubicaciones de Amazon GameLift Servers alojamiento. Con las balizas de ping, puedes recopilar datos de latencia precisos para tomar decisiones informadas sobre la ubicación de los servidores del juego y mejorar el emparejamiento de jugadores en función de los requisitos de latencia.

Cómo funcionan las balizas de ping UDP

Amazon GameLift Serversproporciona puntos finales UDP fijos (balizas de ping) en cada ubicación de alojamiento donde puedes implementar servidores de juegos. Como la mayoría de los servidores de juegos se comunican mediante UDP, medir la latencia con balizas de ping UDP proporciona resultados más precisos que con pings ICMP. Los dispositivos de red suelen gestionar los paquetes ICMP de forma diferente a los paquetes UDP, lo que puede provocar que las mediciones de latencia no reflejen el rendimiento real que experimentarán los jugadores.

Con las balizas de ping UDP, tu cliente de juego puede enviar mensajes UDP a estos puntos finales y recibir respuestas asíncronas, lo que te proporciona mediciones de latencia que representan mejor las condiciones reales del tráfico del juego entre el dispositivo del jugador y las posibles ubicaciones de alojamiento. Los puntos finales son permanentes y permanecen disponibles siempre que se pueda alojar el juego en esa ubicaciónAmazon GameLift Servers.

Casos de uso habituales de las balizas de ping UDP

Puedes usar las balizas de ping UDP de varias maneras para optimizar la experiencia de red de tu juego.

Elegir las ubicaciones de alojamiento óptimas

Recopila datos de latencia en diferentes regiones geográficas para identificar las mejores ubicaciones principales y de respaldo para alojar los servidores de juegos para tu base de jugadores.

Coloca las sesiones de juego en función de la latencia de los jugadores

Incluye los datos de latencia de los jugadores cuando solicites nuevas sesiones de juego para ayudarte a elegir las ubicaciones que ofrezcan la experiencia de latencia más baja.

Optimizar el emparejamiento en función de la latencia

Proporciona datos de latencia de los jugadores cuando solicites el emparejamiento para ayudar a emparejar a jugadores con perfiles de latencia similares y colocar las sesiones de juego en ubicaciones óptimas para los jugadores emparejados.

nota

Al crear solicitudes de emparejamiento, no debes proporcionar información de latencia a ubicaciones en las que no tengas flotas. Si lo haces, Amazon GameLift Servers podrías intentar colocar la sesión de juego en ubicaciones donde no haya capacidad de flota, lo que provocará errores en las solicitudes de emparejamiento.

Obtener puntos finales de baliza

Para recuperar la información del dominio y el puerto de la baliza de ping para Amazon GameLift Servers las ubicaciones, utilice la operación ListLocationsAPI. El conjunto de ubicaciones que devuelve esta API depende de la Región de AWS que especifiques al llamarla (o de tu región predeterminada si no especificas ninguna). Cuando llamas desde:

  • Una región de origen de una flota que admite múltiples ubicaciones: la API devuelve información de todas las ubicaciones de alojamiento

  • Una región de origen de una flota que admite una sola ubicación: la API devuelve la información de esa ubicación

Ten en cuenta que si llamas a esta API desde una ubicación que solo puede ser una ubicación remota en una flota con varias ubicaciones, la API devolverá un error porque ese tipo de ubicación no tiene un punto de conexión de servicio.

Consulta la tabla de ubicaciones compatibles AWS Ubicaciones compatibles para identificar las regiones de origen que admiten flotas de una o varias ubicaciones.

Ejemplo

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

Esto Región de AWS admite flotas con múltiples ubicaciones, por lo que se devolverán ubicaciones múltiples. A continuación, se muestra un ejemplo de uno de los valores devueltos:

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

Almacene en caché la información de la baliza de ping en lugar ListLocations de llamar antes de cada medición de latencia. La información del dominio y el puerto es estática y la API no está diseñada para solicitudes de gran volumen.

Implementación de mediciones de latencia

Siga estas prácticas recomendadas al implementar mediciones de latencia mediante balizas de ping UDP:

  1. Almacene la información de las balizas de ping mediante uno de estos enfoques:

    • Codifica los puntos finales en el cliente del juego.

    • Guarda en caché la información en el backend del juego.

    • Implementa un mecanismo de actualización periódica (diaria/semanal) para actualizar la información.

  2. Enviar mensajes de ping UDP:

    • Pon lo que quieras en el cuerpo del mensaje, siempre que no esté vacío, y mantén los mensajes por debajo del tamaño máximo de 300 bytes.

    • Respeta los siguientes límites de velocidad para cada ubicación:

      • 3 transacciones por segundo (TPS) por combinación única de puerto y dirección IP de remitente

      • 1000 TPS por dirección IP de remitente única

  3. Calcule la latencia:

    • Envía varios pings a cada ubicación para calcular la latencia media.

    • Considere la posibilidad de enviar pings simultáneos a varias ubicaciones para obtener resultados más rápidos.

    • Usa la lógica de reintento según sea necesario para enviar nuevos paquetes para cualquier paquete que no se haya devuelto en poco tiempo (normalmente de 1 a 3 segundos), ya que UDP no garantiza la entrega al 100%.

    • Calcula la diferencia de tiempo entre el envío de un mensaje y la recepción de la respuesta.

    • Si una gran parte de los envíos de mensajes UDP a una ubicación no obtienen una respuesta constante, calcula la latencia utilizando los pings ICMP a nuestros puntos finales de Amazon GameLift Servers servicio estándar como alternativa.

sugerencia

Te recomendamos que incluyas el puerto 7770 siempre que documentes la lista de puertos que tus jugadores deben tener abiertos en su red local. Esta es otra razón por la que deberías disponer de una alternativa para medir la latencia (mediante ICMP, por ejemplo) en caso de que este puerto esté bloqueado.

Ejemplos de código

Estos son algunos ejemplos sencillos que muestran cómo enviar pings UDP y calcular la latencia.

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