Qu'est-ce qu'une mise à jour de la fenêtre TCP?

je crée mon propre logiciel serveur personnalisé pour un jeu en Java (le jeu et le logiciel serveur original ont été écrits en Java). Il n'y a pas de documentation de protocole disponible, donc je dois lire les paquets avec Wireshark.

pendant qu'un client se connecte le serveur lui envoie le fichier de niveau au format Gzip. À environ 94 paquets dans l'envoi du niveau, mon serveur plante le client avec un ArrayIndexOutOfBoundsException. Selon le fichier de capture de l'original serveur, il envoie une mise à jour de la fenêtre TCP vers ce point. Qu'est-ce qu'une mise à jour de fenêtre TCP, et comment l'envoyer en utilisant un SocketChannel?

13
demandé sur phpscriptcoder 2009-09-23 18:22:28

7 réponses

les fenêtres TCP sont utilisées pour le contrôle de flux entre les pairs sur une connexion. Avec chaque paquet ACK, un hôte enverra un champ "window size". Ce champ indique le nombre d'octets de données de l'hôte peut recevoir avant il est plein. L'expéditeur n'est pas censé envoyer plus de cette quantité de données.

la fenêtre peut se remplir si le client ne reçoit pas les données assez rapidement. En d'autres termes, les tampons TCP peuvent se remplir pendant que l'application est hors de faire quelque chose d'autre que la lecture de son socket. Lorsque cela se produit, le client envoie un paquet ACK avec le bit "window full". À ce moment, le serveur est censé arrêter d'envoyer des données. Tout paquet envoyé à une machine avec une pleine fenêtre être accusé de réception. (Cela provoquera la retransmission d'un expéditeur mal conduit. Un expéditeur qui se comporte bien amortira simplement les données sortantes. Si le tampon sur le côté d'envoi remplit aussi, alors l'application d'envoi bloquera quand il essaie d'écrire plus de données à la socket!)

c'est un décrochage TCP. Cela peut se produire pour de nombreuses raisons, mais en fin de compte, cela signifie simplement que l'émetteur transmet plus rapidement que le récepteur lit.

une fois que l'application de l'extrémité de réception revient à la lecture de la socket, il drainera certaines des données tamponnées, ce qui libère de l'espace. Le destinataire envoie alors un paquet" window update " pour indiquer à l'expéditeur la quantité de données qu'il peut transmettre. L'émetteur commence à transmettre ses données tamponnées et la circulation doit être normale.

bien sûr, vous pouvez obtenir répété étals si le récepteur est toujours lent.

j'ai formulé cela comme si l'expéditeur et le destinataire étaient différents, mais en réalité, les deux pairs échangent des mises à jour de fenêtre avec chaque paquet ACK, et chaque côté peut faire remplir sa fenêtre.

le message général est que vous n'avez pas besoin d'envoyer des paquets de mise à jour de fenêtre directement. Il serait en fait une mauvaise idée d'usurper l'identité d'un jusqu'.

en ce qui concerne l'exception que vous voyez... il est peu probable qu'elle soit causée ou empêchée par le paquet de mise à jour de la fenêtre. Cependant, si le client ne lit pas assez vite, vous risquez de perdre des données. Dans votre serveur, vous devriez vérifier la valeur de retour de votre Socket.write() appels. Il pourrait être inférieur au nombre d'octets que vous essayez d'écrire. Cela se produit si le tampon d'émission de l'expéditeur est plein, ce qui peut se produire lors d'un décrochage TCP. Vous risquez de perdre de octet.

par exemple, si vous essayez d'écrire 8192 octets avec chaque appel à écrire, mais qu'un des appels renvoie 5691, alors vous devez envoyer les 2501 octets restants sur le prochain appel. Sinon, le client ne verra pas le reste du bloc de 8K et votre fichier sera plus court du côté du client que du côté du serveur.

51
répondu mtnygard 2016-07-26 00:27:50

cela se produit très profondément dans la pile TCP/IP; dans votre application (serveur et client), vous n'avez pas à vous soucier de windows TCP. L'erreur doit être autre chose.

6
répondu Aaron Digulla 2009-09-23 14:29:17

une mise à jour de la fenêtre TCP A à voir avec la communication de la taille du tampon disponible entre l'expéditeur et le destinataire. Un ArrayIndexOutOfBoundsException n'est pas la cause probable de cela. Le plus probable est que le code attend une sorte de données qu'il ne reçoit pas (très probablement bien avant ce point qu'il est seulement maintenant référencement). Sans voir le code et la trace de la pile, il est vraiment difficile d'en dire plus.

2
répondu Yishai 2009-09-23 14:34:35

TCP WindowUpdate-indique que le segment était un segment de WindowUpdate pur. Une WindowUpdate se produit lorsque l'application du côté récepteur a consommé des données déjà reçues du tampon RX, ce qui fait que la couche TCP envoie une WindowUpdate à l'autre côté pour indiquer qu'il y a maintenant plus d'espace disponible dans le tampon. Généralement observée après une condition de "ZEROWINDOW" TCP. Une fois que l'application sur le récepteur récupère les données du tampon TCP, libérant ainsi espace, le destinataire doit informer l'expéditeur que la condition TCP ZeroWindow n'existe plus en envoyant une WindowUpdate TCP qui annonce la taille actuelle de la fenêtre.

https://wiki.wireshark.org/TCP_Analyze_Sequence_Numbers

2
répondu SimonZC 2015-09-07 13:01:54

Vous pouvez plonger dans ce site web http://www.tcpipguide.com/free/index.htm pour beaucoup d'informations sur le protocole TCP/IP.

0
répondu Jackson 2009-09-23 14:33:58

avez-vous un détails exception?

il n'est probablement pas lié au paquet de mise à jour de la fenêtre TCP

(l'avez-vous vu répéter exactement pour plusieurs instances?)

Plus probablement liée à votre code de traitement qui fonctionne sur les données reçues.

0
répondu nik 2009-09-23 14:39:19

ce n'est normalement qu'un déclencheur, pas la cause de votre problème.

par exemple, si vous utilisez le sélecteur NIO, une mise à jour de la fenêtre peut déclencher le réveil d'un canal d'écriture. Cela déclenche à son tour la mauvaise logique de votre code.

obtenir un stactrace et il vous montrera la cause profonde.

0
répondu ZZ Coder 2009-09-23 14:40:58