3

J'écris un serveur socket et un client de jeu flash. Le jeu nécessite des commandes en temps réel telles que le mouvement et le virage. Il est important que ces commandes soient envoyées par le serveur au client le plus rapidement possible car les autres clients désynchroniseraient beaucoup avec le client en déplacement/virage.Utilisation de TCP pour les commandes en temps réel: l'algorithme de Nagle provoque des retards énormes, que dois-je faire?

Voici un exemple du problème causé par l'arithmétique Nagle:

Remarque: voir le tableau de commande ci-dessous si vous souhaitez comprendre ce que ces commandes signifient.

Le premier est le navire je me suis déplacé (déplacé vers l'avant + droite, en avant a été reçu, mais droit de ne pas)

L'envoi de commandes clients:

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 

Les commandes de réception de client:

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 

« moment » est un terme étrange qui ne veut pas dire ce que je suis en train de dire, mais ici, il semble que le laps de temps en millisecondes après la commande précédente

  1. aller de l'avant envoyer par le client A (moment: 0), reçu par le client B (instant: 0)

  2. virage à droite envoyer par le client A (moment: 0), reçu par B (moment: 155) client

  3. butée mobile envoyer par le client A (moment: 108), reçue par B client (moment: 0)

  4. arrêt tournant envoyer par le client A (moment: 0), reçu par B client (moment: 0)

  5. aller de l'avant envoyer par le client A (moment: 1283), reçu par B (moment: 1236) client

  6. tourner à droite envoyer par le client A (moment: 1), reçu par B (moment: 273) client

  7. stop mouvement envoi par le client A (moment: 186), reçu par le client B (instant: 0)

  8. arrêt tournant envoyer par le client A (moment: 30), reçue par B client (moment: 0)

Voici le tableau de commande correspondant aux commandes:

client-> serveur

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

Server-> Client

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

Alors, ce que vous pouvez voir est que les commandes sont totalement desynched à cause de "Nagle". Cela provoque la réception de la commande stop movement par les autres clients en même temps que la commande start movement, ce qui empêche le joueur de bouger du tout. C'est pourquoi j'ai besoin que ces commandes soient envoyées en temps réel, le plus rapidement possible par le serveur TCP. Une solution facile serait de désactiver simplement Nagle.Cependant, j'ai googled (notez que sa suggestion sur le message tcp partial est implémentée dans mon système mais n'a rien à voir avec le timing) et j'ai remarqué que les gens ne déconseillent absolument pas de désactiver Nagle.

Est-ce vrai que je ne devrais pas désactiver l'algorithme Nagle pour cette cause et que je devrais chercher une autre solution? Pourquoi pas)?

Merci d'avance. - Tom

+0

Nagle * algorithme *, pas 'arithmétique'. – EJP

Répondre

4

Vous souhaitez utiliser TCP_NODELAY pour désactiver l'algorithme nagle pour ce socket. Il ya des paramètres dans les systèmes d'exploitation modernes pour le désactiver à l'échelle du système, et que IS est mal vu, mais il n'y a pas de raison que vous ne devriez pas le faire avec un socket que vous savez avoir besoin d'une faible latence.

setsockopt(TCP_NODELAY)

1

Notez que votre commutateur, routeur, swithcgear fournisseur d'accès Internet .... etc peuvent tout aussi Nagle leurs petits tripes occultants. Les petites bestioles sales peuvent lire des paquets, donc ils prennent des libertés et les réécrivent parfois ..

Jetez un coup d'œil à RTP (qui fonctionne sur UDP) pour une approche plus résorbable par le réseau.

2

Si cela doit être aussi rapide que possible, vous devez utiliser UDP.

Toutefois, notez que TCP fournit la garantie de livraison et pour alors que UDP fournit aucune. Ce point semble être un point important dans cette application, donc vous devrez superposer votre propre mécanisme de commande de reconnaissance/réessayer.

Si vous voulez rester avec TCP, TCP__NODELAY vous aidera. Au fur et à mesure de l'avancement de votre jeu, vous pourriez avoir besoin d'un flux de données que TCP sera bien adapté sans TCP_NODELAY. RFC1006 formalise un mécanisme d'envoi de paquets sur un flux TCP.

+0

L'OP n'a * pas * dit qu'il avait besoin d'être le plus rapide possible. Il a simplement déclaré qu'il voulait que les données soient envoyées immédiatement, ce qui est sensiblement différent. Toutes choses étant égales par ailleurs, il vaut beaucoup mieux tourner la tête que de sauter directement à l'UDP. – Tom

+0

C'est confus, deux personnes ayant le même nom dans un thread. – Tom

1

Si votre objectif est que les vaisseaux finissent par faire la même chose sur l'écran de tout le monde, vous devrez envoyer des mises à jour de position. Vous ne pouvez pas supposer que parce que le client A fait:

  • Tourner à gauche
  • Attendez 100ms
  • Cesser de tourner

que le client B verra ce délai même 100ms exact. La mise en mémoire tampon de Nagle rend cela encore plus extrême - mais il y aura toujours de la gigue et des retards variables.

Vous avez vraiment besoin d'envoyer quelque chose comme:

  • (Je suis à la position X1, Y1 avec la position Z1) Tourner à gauche
  • (Je suis à la position X2, Y2 avec la position Z2) Arrêter de tourner

Pour que les clients effectuent une resynchronisation continue.

+0

J'aurais dû fournir plus d'informations générales. Je fais cela, alors ne vous inquiétez pas. Le problème principal que j'ai soulevé dans ce fil a été résolu. Merci. – Tom

1

Notez que Windows implémente delayed ACK ainsi que Nagle. Cela peut entraîner 200 ms de retard supplémentaires sur les messages TCP individuels. Pour autant que je sache, vous ne pouvez pas changer cela sur Windows, sauf via une clé de registre (et un hotpatch pour activer la clé de registre dans certains cas).

Questions connexes