

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á.

# Sinalizadores de ping UDP do Amazon GameLift Servers
<a name="reference-udp-ping-beacons"></a>

Os sinalizadores de ping UDP fornecem uma maneira de medir a latência da rede entre os dispositivos dos jogadores e os locais de hospedagem do Amazon GameLift Servers. Com sinalizadores de ping, você pode coletar dados de latência precisos para tomar decisões informadas sobre a colocação 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
<a name="reference-how-beacons-work"></a>

O Amazon GameLift Servers fornece endpoints UDP fixos (sinalizadores 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 sinalizadores 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 sinalizadores 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 o Amazon GameLift Servers ofereça suporte à hospedagem de jogos nesse local.

## Casos de uso comuns para sinalizadores de ping UDP
<a name="reference-beacons-common-use-cases"></a>

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

**Escolhendo os 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 a criação de partidas com base na latência**  
Forneça dados de latência do jogador ao solicitar a criação de partidas 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 criação de partidas, você não deve fornecer informações de latência para locais onde você não tem frotas. Se você fizer isso, o 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 criação de partidas.

## Obtenção de endpoints de sinalizador
<a name="reference-beacons-getting-endpoints"></a>

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 [ListLocations](https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_ListLocations.html)API. 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ê chama de:
+ **Uma região de origem de uma frota que oferece suporte a vários locais**: a API retorna informações de *todos* os locais de hospedagem
+ **Uma região de origem de uma frota que oferece suporte a um só local**: a API retorna informações para aquele local

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

Consulte a tabela de locais compatíveis em [AWS Localizações suportadas](gamelift-regions.md#gamelift-regions-hosting-home) 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. Veja o 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 chamar `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.

## Implementação de medidas de latência
<a name="reference-beacons-measuring-latency"></a>

Siga estas práticas recomendadas ao implementar medidas de latência usando sinalizadores de ping UDP:

1. Armazene as informações do sinalizador de ping usando uma dessas abordagens:
   + Codifique os endpoints do cliente do jogo.
   + Armazene as informações no backend do seu jogo.
   + Implemente um mecanismo de atualização periódica (diária/semanal) para atualizar as informações.

1. 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:
     + Combinação de até 3 transações por segundo (endereço IP e porta) do remetente
     + 1000 TPS por endereço IP exclusivo do remetente

1. Calcular 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 [endpoints de serviço do Amazon GameLift Servers](https://docs.aws.amazon.com/general/latest/gr/gamelift.html#gamelift_region) 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
<a name="reference-beacons-code-examples"></a>

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

------