Qual é a solução alternativa para o reconhecimento atrasado do TCP?
Enviei um videogame online (baseado em grade) que usa o protocolo TCP para garantir uma comunicação confiável em uma topologia de rede servidor-cliente. Meu jogo funciona razoavelmente bem, mas sofre com uma latência maior que o esperado (jogos TCP semelhantes no gênero parecem fazer um trabalho melhor em manter a latência em um nível mínimo).
Ao investigar, descobri que a latência é inesperadamente alta para clientes executandoMicrosoft Windows (em oposição aMac OS X clientes). Além disso, descobri que, se um cliente Windows definirTcpAckFrequency=1
no registro e reinicia a máquina, a latência se torna normal.
Parece que meu design de rede não levou em consideração o atraso no reconhecimento:
Um design que não leva em consideração a interação deatraso no reconhecimento, o algoritmo Nagle e o buffer Winsock podem afetar drasticamente o desempenho. (http://support.microsoft.com/kb/214397)
No entanto, estou achando quase impossível levar em conta o reconhecimento atrasado no meu jogo (ou em qualquer outro jogo). De acordo com o MSDN, a pilha TCP da Microsoft usa os seguintes critérios para decidir quando enviar um ACK nos pacotes de dados recebidos:
Se o segundo pacote de dados for recebido antes que o timer de atraso expire (200ms), o ACK será enviado.Se houver dados a serem enviados na mesma direção que o ACK antes que o segundo pacote de dados seja recebido e o temporizador de atraso expire, o ACK será transferido para o segmento de dados e enviado imediatamente.Quando o temporizador de atraso expirar (200 ms), o ACK é enviado.(http://support.microsoft.com/kb/214397)
Lendo isso, presume-se que a solução alternativa para reconhecimento atrasado na pilha TCP da Microsoft seja a seguinte:
Desative o algoritmo Nagle (TCP_NODELAY).Desative o buffer de envio do soquete (SO_SNDBUF
= 0), para que uma chamada parasend
pode-se enviar um pacote.Ao ligarsend
, se não se espera que mais dados sejam enviados imediatamente, ligue parasend
novamente com um byte único de dados que serão descartados pelo receptor.Com essa abordagem, o segundo pacote de dados será recebido pelo receptor aproximadamente ao mesmo tempo que o pacote de dados anterior. Como resultado, oACK
deve ser enviado imediatamente do destinatário ao remetente (emulando o queTcpAckFrequency=1
faz no registro).
No entanto, nos meus testes, isso aumentou a latência em cerca de metade do que a edição do Registro faz. o que estou perdendo?
P: Por que não usar UDP?UMA: Eu escolhi o TCP porque cada pacote que eu envio precisa chegar (e estar em ordem); não há pacotes que não valham a pena retransmitir se eles se perderem (ou ficarem desordenados). Somente quando os pacotes podem ser descartados / não ordenados, o UDP pode ser mais rápido que o TCP!