Amazon GameLift ServersSinalizadores de ping UDP - Amazon GameLift Servers

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Amazon GameLift ServersSinalizadores de ping UDP

Os beacons de ping UDP fornecem uma maneira de medir a latência da rede entre os dispositivos dos jogadores e os locais de hospedagem. Amazon GameLift Servers Com sinalizadores de ping, você pode coletar dados de latência precisos para tomar decisões informadas sobre o posicionamento do servidor do jogo e melhorar a combinação de jogadores com base nos requisitos de latência.

Como funcionam os sinalizadores de ping UDP

Amazon GameLift Serversfornece endpoints UDP fixos (beacons de ping) em cada local de hospedagem onde você pode implantar servidores de jogos. Como a maioria dos servidores de jogos se comunica usando UDP, medir a latência com beacons de ping UDP fornece resultados mais precisos do que usando pings ICMP. Os dispositivos de rede geralmente lidam com pacotes ICMP de forma diferente dos pacotes UDP, o que pode levar a medições de latência que não refletem o verdadeiro desempenho que seus jogadores experimentarão.

Com os beacons de ping UDP, seu cliente de jogo pode enviar mensagens UDP para esses endpoints e receber respostas assíncronas, fornecendo medidas de latência que representam melhor as condições reais de tráfego do jogo entre o dispositivo de um jogador e possíveis locais de hospedagem. Os endpoints são permanentes e permanecem disponíveis desde que ofereçam Amazon GameLift Servers suporte à hospedagem de jogos nesse local.

Casos de uso comuns para beacons de ping UDP

Você pode usar beacons de ping UDP de várias maneiras para otimizar a experiência de rede do seu jogo.

Escolhendo locais de hospedagem ideais

Colete dados de latência em diferentes regiões geográficas para identificar os melhores locais primários e de backup para hospedar servidores de jogos para sua base de jogadores.

Colocar sessões de jogo com base na latência do jogador

Inclua dados de latência do jogador ao solicitar novas sessões de jogo para ajudar a escolher locais que ofereçam a experiência de menor latência.

Otimizando o matchmaking com base na latência

Forneça dados de latência do jogador ao solicitar matchmaking para ajudar a combinar jogadores com perfis de latência semelhantes e colocar as sessões de jogo em locais ideais para jogadores pareados.

nota

Ao criar solicitações de matchmaking, você não deve fornecer informações de latência para locais onde você não tem frotas. Se você fizer isso, Amazon GameLift Servers pode tentar colocar a sessão do jogo em locais onde não há capacidade da frota, resultando em falhas na solicitação de matchmaking.

Obtendo endpoints de beacon

Para recuperar as informações do domínio e da porta do sinalizador de ping para Amazon GameLift Servers locais, use a operação da ListLocationsAPI. O conjunto de locais retornados por essa API depende do Região da AWS que você especifica ao chamá-la (ou da sua região padrão, se você não especificar uma). Quando você liga de:

  • Uma região de origem de uma frota que suporta vários locais: a API retorna informações de todos os locais de hospedagem

  • Uma região de origem de uma frota que suporta um único local: a API retorna informações desse local

Observe que, se você chamar essa API usando um local que só pode ser remoto em uma frota com vários locais, a API retornará um erro porque esse tipo de local não tem um ponto final de serviço.

Consulte a tabela de locais compatíveis AWS Localizações suportadas para identificar as regiões de origem que oferecem suporte a frotas de um ou vários locais.

Exemplo

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

Isso Região da AWS suporta frotas com vários locais, portanto, vários locais serão devolvidos. Aqui está um exemplo de um dos valores de retorno:

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

Armazene em cache as informações do sinalizador de ping em vez de ligar ListLocations antes de cada medição de latência. As informações do domínio e da porta são estáticas e a API não foi projetada para solicitações de alto volume.

Implementando medições de latência

Siga estas melhores práticas ao implementar medições de latência usando beacons de ping UDP:

  1. Armazene as informações do sinalizador de ping usando uma das seguintes abordagens:

    • Codifique os endpoints em seu cliente de jogo.

    • Armazene as informações no back-end do seu jogo.

    • Implemente um mecanismo de atualização periódica (diária/semanal) para atualizar as informações.

  2. Envie mensagens de ping UDP:

    • Coloque o que quiser no corpo da mensagem, desde que não esteja vazio, e você manterá as mensagens abaixo do tamanho máximo de 300 bytes.

    • Observe os seguintes limites de tarifa para cada local:

      • 3 transações por segundo (TPS) por combinação exclusiva de endereço IP e porta do remetente

      • 1000 TPS por endereço IP exclusivo do remetente

  3. Calcule a latência:

    • Envie vários pings para cada local para calcular uma latência média.

    • Considere enviar pings simultâneos para vários locais para obter resultados mais rápidos.

    • Use a lógica de repetição conforme necessário para enviar novos pacotes para qualquer pacote que não tenha sido devolvido em pouco tempo (normalmente de 1 a 3 segundos), pois o UDP não tem entrega 100% garantida.

    • Calcule a diferença de tempo entre enviar uma mensagem e receber a resposta.

    • Se uma grande parte dos pings UDP para um local consistentemente não obtiverem uma resposta, calcule a latência usando pings ICMP para nossos terminais de Amazon GameLift Serversserviço padrão como alternativa.

dica

Recomendamos que você inclua a porta 7770 sempre que documentar a lista de portas que seus players devem ter abertas na rede local. Esse é outro motivo pelo qual você deve ter um substituto para medir a latência (usando ICMP, por exemplo) caso essa porta esteja bloqueada.

Exemplos de código

Aqui estão alguns exemplos simples que mostram como enviar pings UDP e calcular a latência.

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