Pergunta

Eu estou escrevendo um cliente do servidor de soquete e jogo flash. O jogo requer comandos em tempo real tais como o movimento e girando. É importante para esses comandos para ser enviada pelo servidor para o cliente o mais rápido possível, porque os outros clientes, caso contrário, desynchronise muito com o cliente em movimento / girar.

Este é um exemplo do problema causado pela aritmética Nagle:

Nota :. Consulte a tabela de comando abaixo se você quiser entender o que esses comandos significa

O primeiro é o navio que me mudei (movido para a frente + direita, para frente foi recebido, mas direito de não)

O cliente do envio de comandos:

84796: Sending data: 2#4
84796: Sending data: 2#2
84904: Sending data: 2#3
84904: Sending data: 2#0
86187: Sending data: 2#4
86188: Sending data: 2#2
86374: Sending data: 2#3
86404: Sending data: 2#0

O cliente receber comandos:

79244: Raw receive: 3#3#4$
79244: New command: 3#3#4
79398: Raw receive: 3#3#2$3#3#3$3#3#0$
79399: New command: 3#3#2
79399: New command: 3#3#3
79399: New command: 3#3#0
80635: Raw receive: 3#3#4$
80635: New command: 3#3#4
80908: Raw receive: 3#3#2$3#3#3$3#3#0$
80908: New command: 3#3#2
80908: New command: 3#3#3
80908: New command: 3#3#0

"momento" é um termo estranho que não significa que eu estou tentando dizer, mas aqui parece que a quantidade de tempo em milissegundos após o comando anterior

  1. avançar enviar por cliente A (momento: 0), recebido pelo cliente B (momento: 0)

  2. vire à direita enviar por cliente A (momento: 0), recebido pelo cliente B (momento: 155)

  3. parar de se mover enviar por cliente A (momento: 108), recebido pelo cliente B (momento: 0)

  4. viragem parada enviar por cliente A (momento: 0), recebido pelo cliente B (momento: 0)

  5. avançar enviar por cliente A (momento: 1283), recebido pelo cliente B (momento: 1236)

  6. vire à direita enviar por cliente A (momento: 1), recebido pelo cliente B (momento: 273)

  7. movimento parada enviar por cliente A (momento: 186), recebido pelo cliente B (momento: 0)

  8. viragem parada enviar por cliente A (momento: 30), recebido pelo cliente B (momento: 0)

Esta é a tabela de comando correspondente com os comandos:

Client-> Servidor

2# (movement info)
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

Server-> Cliente

3# (movement info)
[shipId]#
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

Então, o que você pode ver é que os comandos são totalmente desynched por causa de "Nagle". Isso faz com que o comando de movimento de parada para ser recebido por outros clientes, ao mesmo tempo que o comando movimento começo, fazendo com que esse jogador não se mover.

É por isso que eu preciso que esses comandos ser enviado em tempo real, o mais rápido possível pelo servidor TCP. Um reparo fácil seria a de simplesmente desativar Nagle. No entanto, tenho googled (note que a sua sugestão sobre tcp mensagem parcial é implementado no meu sistema, mas não tem nada a ver com o tempo) um pouco e notei que as pessoas absolutamente não recomenda a desativação Nagle.

É verdade que eu não deveria desativar o algoritmo Nagle para esta causa e deve, em vez procurar uma outra solução? Por que (não)?

Obrigado antecipadamente. - Tom

Foi útil?

Solução

Você quer usar TCP_NODELAY para desligar o algoritmo Nagle para esse socket. Há configurações em sistemas operacionais modernos para desativá-lo em uma base de todo o sistema, e que é desaprovada, mas não há razão que você não deve fazê-lo com uma tomada que você sabe que precisa de baixa latência em .

setsockopt (TCP_NODELAY)

Outras dicas

Se ele precisa ser tão rápido quanto possível, você deve usar UDP.

No entanto, nota que o TCP fornece garantia de entrega e fim enquanto UDP fornece nenhum.

Esse ponto parece ser um criticamente ponto importante nesta aplicação para que você teria para a camada seu próprio mecanismo de comando de pedidos de reconhecimento / repetição no topo.

Se você quiser ficar com TCP, TCP__NODELAY vai ajudar. Como o jogo avança você pode acabar exigindo um fluxo de dados que o TCP será bem adequado para sem TCP_NODELAY.

RFC1006 formaliza um mecanismo para o envio de pacotes ao longo de um fluxo TCP.

Note que o seu switch, roteador, swithcgear do ISP .... etc podem todos também Nagle suas entranhas pequenas black out. Os animais sujos pequenos pode ler pacotes, assim que tomar liberdades e reescrevê-los, às vezes ..

Dê uma olhada na RTP (que corre sobre UDP) para uma abordagem -survivable mais rede.

Se o seu objetivo é ter os navios acabam fazendo a mesma coisa na tela de todos, você vai ter que enviar atualizações de posição. Você não pode assumir que apenas porque o cliente A fez:

  • Vire à esquerda
  • 100ms de espera
  • parar de girar

que o Cliente B vai ver que exata atraso mesmos 100ms. O Nagle buffer só faz isso mais extrema -., Mas sempre haverá jitter e variando atrasos

Você realmente precisa enviar algo como:

  • (estou na posição X1, Y1 com a rubrica Z1) Vire à esquerda
  • (am I a posição X2, Y2 com posição Z2) pare de rodar

Para que os clientes estão continuamente resynchronising.

Note que o Windows implementos adiada ACK , bem como Nagle. Isto pode lhe dar uma 200ms extras de atraso em mensagens TCP individuais. Tanto quanto eu sei, você não pode mudar isso no Windows, exceto por meio de uma chave de registro (e um hotpatch para ativar a chave de registro em alguns casos).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top