Sincronização de clock de programas cliente - Conceitos / Teoria - Artigos - Articles - Fórum

Jump to content

Bem vindo à Unidev
Registre para ter acesso a todos os recursos do site. Uma vez registrado e logado, você poderá criar tópicos, postar em tópicos já existentes, gerenciar seu perfil e muito mais. Se você já tem uma conta, faça login aqui - ou então crie aqui uma conta agora mesmo!
- - - - -
Photo

Sincronização de clock de programas cliente


por Pablo marquez

INTRODUÇÃO

Os jogos multiplayer muitas vezes precisam lidar com a natureza complexa da tecnologia de rede. Mais notavelmente, jogos multiplayer na Internet representam um desafio maior para os desenvolvedores do que os jogos escritos apenas para rodar em ambientes de rede local (LAN). Um desses desafios é o atraso que existe a partir do momento em que um processo envia uma mensagem através da rede para o momento em que a mensagem é recebida por outro processo. Este atraso é conhecido como latência de rede, e é tanto uma consequência de restrições físicas do nosso mundo e da concepção da tecnologia de rede (protocolos).

A latência da rede, informalmente conhecido como LAG, representa um sério desafio para os desenvolvedores de jogos multiplayer. LAG pode ter efeitos desastrosos sobre a experiência de jogo do jogador, tornando o jogo não-jogável.

A latência pode mudar ao longo de uma sessão de jogo, o comportamento dinâmico da rede requer uma solução que pode detectar estas mudanças e reagir a minimizar o seu impacto no jogo.

A sincronização de clock do cliente é uma técnica simples que pode ser utilizado para lidar com a latência da rede. Não é uma solução perfeita, mas em alguns casos específicos, pode melhorar significativamente a experiência dos usuários, mascarando os efeitos da latência de rede e fazendo o jogo parecer agradável e justo.

O documento descreve como apresentado para sincronizar os clocks do cliente através da rede. A primeira parte do documento descreve como as mensagens são codificadas antes de enviá -los pela rede. A parte final do documento descreve as mensagens que os clientes eo Exchange Server para sincronizar os clocks.

CENÁRIO DO JOGO

Lembre-se, o nosso objetivo é que o jogo possa reagir ao comportamento dinâmico da rede. Para este efeito, vamos supor que estamos trabalhando em um jogo multiplayer de arcade simples em que dois jogadores competem.

Clocks dos programas são o mecanismo de sincronização principal e único em que nós vamos estar contando com a alcançar o nosso objetivo. Um clock é apenas um contador simples que varia de 0 até N, com o valor atual de um relógio que representa o número de milissegundos que se passaram desde que o jogo começou.

É essencial que, quando uma sessão de jogo começa, que é quando começa o jogo em si, todos os três clocks (dois clientes e servidor) estejam sincronizados e têm o seu valor inicial igual a zero. O algoritmo descrito posteriormente neste artigo, vamos fazer isso.

Uma vez que os clocks são sincronizados, podemos usá-los por pelo menos três funções muito importantes:

- O servidor pode informar aos clientes principais mudanças de estado no ambiente de jogo.
- O servidor pode usar o relógio juntamente com data e hora da mensagem do cliente para arbitrar conflitos.
- Os clientes podem usar os relógios e marcas de tempo das mensagens recebidas para detectar mudanças de latência de rede. Quando o cliente percebe uma mudança na latência, que a escala da velocidade do local de Avatar para minimizar o efeito da latência .

Aqui está uma classe C ++ para o clock virtual do jogo:



class VClock {
DWORD mRealStart;
bool  mStarted;
public:
VClock() : mRealStart(0) {} ;
bool Started() const { return mStarted ; }
void Start( DWORD time_delta )
{
mRealStart=GetTickCount()-time_delta;
mStarted=true;
}
DWORD getTime( ) const 
{
assert(mStarted) ;
return GetTickCount() - mRealStart;
}
};



A função GetTickCount recupera o número de milissegundos que se passaram desde que o computador foi ligado. O valor devolvido é de 8 bytes de comprimento e o maior valor pode ser 49.7 dias, o que é mais do que suficiente para uma sessão de jogo! Caso contrário, o jogador está em grave perigo e precisa buscar ajuda.

O clock real é o valor retornado do GetTickCount. O clock virtual é o valor de GetTickCount menos o instante em que o servidor assinalou o início de uma sessão de jogo.

MENSAGENS DA APLICAÇÃO

O cliente do jogo comunica com o servidor através do envio de mensagens através da rede, o protocolo de transporte usado pelo jogo é TCP. A mensagem é um pedaço de informação que o cliente/servidor quer se comunicar. Por exemplo, um jogador pressionou o botão esquerdo do mouse.

Layout da Mensagem




Posted Image




[Figura 1]

O campo ID tem 2 bytes de comprimento, é um integer usado para identificar diferentes mensagens.
Os valores deste campo são declarados no programa como um tipo enumerativo:



typedef enum commands
{
cmdLOGIN = 0x1U,
cmdERROR = 0x2U,
cmdLOGIN_OK = 0x3U,
cmdMOUSE_LEFT_BUTTON_DOWN = 0x5U,
cmdREADY = 0x9U,
cmdBEGIN_GAME = 0x10U,
cmdGAME_END = 0x11U,
cmdSYNCH_REQUEST = 0x12U,
cmdSYNCH_REPLY = 0x13U,
cmdPRIMARY_CLIENT = 0x14U,
cmdSECONDARY_CLIENT = 0x15U,
cmdSYNCH_DONE = 0x16U,
cmdSYNCH_WAIT = 0x17U
} protoCommands;



O campo SIZE é de dois bytes e especifica o tamanho da mensagem medido em bytes. O menor mensagem tem um tamanho de 4 bytes.

O campo DATA tem comprimento variável. Este campo é usado para comunicar informações adicionais, por exemplo, os dados do campo da mensagem cmdMOUSE_LEFT_BUTTON_DOWN tem a posição do mouse do usuário remoto.

Os campos são codificados/decodificados usando as funções de soquete padrão htons, ntohs, htonl e ntohl. Estas funções convertem um número de 16 bits/32 bits a partir da ordem de byte host (little-endian em processadores Intel) para a ordem de byte de rede (big endian), bem como o contrário.

O campo TIMESTAMP é de 4 bytes, por favor note que este campo só é utilizado uma vez que os clocks foram sincronizados. Ao enviar mensagens, os clientes sempre armazenam o valor de seu clock virtual aqui.

ALGORITMO DE SINCRONIZAÇÃO DE CLOCK

A fim de sincronizar os clocks dos clientes, os programas precisam estimar a latência da rede: a quantidade de tempo que leva uma mensagem para viajar de um

programa cliente para o outro. Por conseguinte, o processo de sincronização do clock tem dois passos: 1) computar a latência da rede e 2) sincronização do sinal de clock.

O diagrama abaixo mostra as mensagens que são trocadas para realizar a sincronização do clock:




Posted Image




[Figura 2]


1 - Cliente Nº1 estabelece uma conexão TCP com o servidor de jogo e envia a mensagem cmdLOGIN. Esta mensagem inclui o ID do jogo que o cliente quer se juntar.
2 - Após o recebimento da mensagem cmdLOGIN, o servidor verifica se o jogo solicitado já tem um cliente primário associado a ele. Se não houver nenhum jogador principal o servidor atribui esse papel ao cliente e envia o cmdPRIMARY_CLIENT mensagem.
3 - Cliente #1 recebe a mensagem cmdPRIMARY_CLIENT. O cliente envia a mensagem para o servidor cmdSYNCH_REQUEST e grava a hora em que a mensagem foi enviada.
4 - O servidor recebe a mensagem cmdSYNCH_REQUEST, mas como o outro jogador ainda não entrou para o jogo, o servidor envia de volta ao cliente a mensagem cmdSYNCH_WAIT. Esta mensagem informa ao cliente que ele deveria tentar novamente mais tarde.
5 - Cliente #1 envia a mensagem para o servidor cmdSYNCH_REQUEST e grava a hora em que a mensagem foi enviada.
6 - Item 4.
7 - Cliente nº2 estabelece uma conexão TCP com o servidor de jogo e envia o cmdLOGIN mensagem. Esta mensagem inclui o ID do jogo que o cliente quer se juntar.
8 - Após o recebimento da mensagem cmdLOGIN, o servidor verifica se o jogo solicitado já tem um cliente primário associado. O jogador primário já se juntou ao jogo, então o servidor atribui o papel secundário a este novo cliente e envia a ele a mensagem cmdSECONDARY_CLIENT.
9 - Cliente #1 envia a mensagem para o servidor cmdSYNCH_REQUEST e grava a hora em que a mensagem foi enviada.
10 - O servidor repassa para o cliente n º 2 a mensagem cmdSYNCH_REQUEST.
11 - Cliente #2 recebe o cmdSYNCH_REQUEST mensagem e envia a mensagem para o servidor cmdSYNCH_REPLY.
12 - Cliente #1 recebe a mensagem cmdSYNCH_REPLY e regista o momento em que ele foi recebido.

[O programa repete os passos de 9,10,11 e 12 várias vezes . As mensagens cmdSYNCH_REQUEST estão espaçadas por 20 milissegundos]

13 - Neste ponto, o cliente primário reuniu os dados necessários para calcular a latência, então agora o cliente calcula a latência, define seu clock a 0 e envia a mensagem cmdSYNCH_DONE. Esta mensagem inclui o cálculo da latência. O cliente primário usa as seguintes estatísticas para estimar a latência:

A(n) = tempo em que a enésima cmdSYNCH_REPLY foi recebida
B(n) = tempo em que a enésima cmdSYNCH_REQUEST foi enviada
X(n) = A(n) - B(n)/2

a) Organizar o X(n) da menor latência para maior e escolher o valor mediano.

B) Calcular o desvio-padrão s² = (Σx² - (Σx)² / n) / n - 1

c) Rejeitar o X(n) valores que não estão no intervalo: I : [ ponto médio - s , ponto médio + s]

d ) Calcule a média Σx/n a partir do intervalo de I, este valor vai ser utilizado como a latência.

14 - O servidor encaminha o cmdSYNCH_DONE mensagem para o cliente secundário.
15 - Cliente #2 recebe a mensagem cmdSYNCH_DONE e define seu clock para 0 + latência
16 - O servidor envia a mensagem cmdLOGIN_OK para ambos os clientes.

Este artigo foi originalmente postado em Gamedev.net
[http://www.gamedev.n...-programs-r2493]



0 Comments