Skip to main content

Parfois, netstat affiche une prise qui semble être bloquée. L'application distante a été arrêtée, parfois même l'application OpenVOS a été arrêtée mais netstat affiche toujours la socket. Cet article explique pourquoi cela se produit et ce que vous pouvez faire pour y remédier.

Une brève introduction aux états du PCT

Si vous cherchez sur Google "tcp state diagram", vous trouverez une pléthore d'images, certaines à peine lisibles, d'autres tout à fait lisibles. Wikimedia en a une très belle avec un code couleur (http://commons.wikimedia.org/wiki/File:TCP_state_diagram.png). Le TCP RFC (793) (http://www.rfc-editor.org/rfc/rfc793.txt) a un diagramme d'état ASCII et explique bien sûr les états en détail.

Les prises peuvent se bloquer lorsqu'elles attendent que l'application locale ou l'hôte distant fasse quelque chose. Cela se produit dans trois états. Dans l'état FIN_WAIT_2, la socket attend que l'hôte distant ferme la connexion. Dans l'état CLOSE_WAIT, elle attend que l'application locale ferme la socket et dans l'état ESTABLISHED, elle attend que l'hôte distant ouvre sa fenêtre d'envoi, ou que l'application locale envoie quelque chose. Si la pile TCP locale a envoyé des données et attend que l'hôte distant reconnaisse qu'elle ne peut pas se bloquer, elle finira par s'arrêter, signalera une erreur à l'application locale et fermera la socket.

État FIN_WAIT_2

C'est peut-être le cas le plus courant de prise coincée qui est appelé dans le CAC. L'application locale a fermé la prise et peut avoir pris fin. La raison typique pour laquelle les sockets sont bloquées dans cet état est que l'application distante est suspendue et ne lit pas sa socket.

Le réglage du paramètre STCP finwait2 à un certain N > 0 fermera les sockets après qu'elles aient été dans le FIN_WAIT_2 pendant N secondes. À partir des versions 14.7.2bg, 14.7.tl1, 15.2.1aa, 15.2.tel.af, 15.3.0bd, 15.3.tel.ag, 16.2.1al, 17.0.0ai, et 17.1, la valeur par défaut est 1200, avant cela la valeur par défaut était 0 (donc si vous voulez que les sockets se ferment, vous devrez le définir vous-même). Vous pouvez voir la valeur actuelle avec la requête list_stcp_params analyze_system, vous pouvez changer la valeur avec la requête set_stcp_param analyze_system. Voir le manuel d'analyse du système OpenVOS (R073), disponible sur http://stratadoc.stratus.com, pour la documentation sur ces demandes.

État CLOSE_WAIT

C'est le deuxième état de prise bloquée le plus courant. Les sockets dans un état CLOSE_WAIT attendent que l'application locale ferme la socket. La raison typique pour laquelle une socket reste dans cet état est que l'application ne lit plus la socket. La façon la plus simple de fermer la socket est de terminer l'application locale.

Si vous ne pouvez pas mettre fin à l'application locale, la seule chose que vous pouvez faire est de créer un paquet avec le drapeau RST (réinitialisation) activé. Pour cela, vous devez connaître les numéros de séquence utilisés par la socket (disponibles grâce à la requête dump_onetcb analyze_system) et disposer d'un utilitaire sur un autre hôte du sous-réseau local qui peut construire et envoyer des paquets IP personnalisés. Ces utilitaires sont disponibles pour les systèmes Windows et Linux.

État ÉTABLI

Comme la plupart du temps netstat affiche les prises dans l'état ÉTABLI, comment pouvez-vous savoir quand la prise est bloquée ? Si vous avez un rapport indiquant que l'hôte distant s'est planté ou que le réseau entre les hôtes local et distant est en panne depuis plus de 10 minutes et que l'application locale attend que le distant lui envoie quelque chose, vous pouvez être pratiquement sûr que la socket est bloquée. Dans ce cas, la valeur de la file d'attente d'envoi (le nombre à gauche de l'adresse IP locale) signalée par netstat sera 0. Par contre, si la valeur de la file d'attente d'envoi est supérieure à 0 et qu'elle y reste, il se peut que l'hôte distant annonce une fenêtre zéro.

Dans le premier cas, à moins que la fonction "keep-alive" ne soit activée, la prise restera dans l'état ÉTABLI jusqu'à ce que l'application locale soit terminée. Si la fonction "keep-alive" est activée, le STCP enverra une sonde après l'expiration du délai de maintien en activité. Si la sonde reste sans réponse, elle sera retransmise, mais après quelques minutes et plusieurs retransmissions, la connexion sera interrompue. Par défaut, l'interface est réglée sur "keep-alive", mais les prises par défaut ne le sont pas non plus. Pour définir keep-alive sur une socket, l'application doit utiliser l'appel de fonction setsockopt. Voir le manuel de programmation TCP/IP (R420) d'OpenVOS STREAMS, également disponible sur http://stratadoc.stratus.com, pour plus de détails. Le temps de maintien en activité par défaut est de 2 heures ; cela signifie que la première sonde de maintien en activité est transmise 2 heures après la réception du dernier segment TCP de l'hôte distant, vous devez donc être patient. Pour ceux qui ne sont pas aussi patients, vous pouvez ajuster le temps de maintien en activité ainsi que le temps entre les sondes et le nombre de sondes avec la requête set_stcp_parameter dans analyze_system. Je ne recommande pas de modifier ces paramètres sans une analyse détaillée.

Si le socket n'a pas de fonction "keep-alive", la seule option simple est de mettre fin à l'application qui possède le socket. Si ce n'est pas une option, il est possible de fermer la socket en lui envoyant un segment avec le drapeau RST activé..

Pour confirmer le deuxième cas, vérifiez la valeur de sndws affichée par la requête dump_onetcb analyze_system. Une valeur de 0 indique une fenêtre fermée. Vous pouvez également exécuter packet_monitor pour suivre la connexion et vérifier la valeur de la fenêtre dans l'en-tête TCP en segments à partir de l'hôte distant. Une valeur de "n.a." indique 0.

Je tiens à souligner qu'il s'agit peut-être d'un état récupérable. Les applications sont parfois retardées et la pile TCP ferme la fenêtre, lorsque l'application est rattrapée, la pile ouvre la fenêtre. Cependant, dans la plupart des cas, je pense qu'on peut supposer sans risque que si l'application ne s'est pas rétablie après quelques minutes, elle ne le fera pas. L'exception pourrait être une imprimante qui n'a plus de papier. Une prise dans cet état peut rester dans cet état même si l'application VOS qui l'a créée se termine.

Ces sockets peuvent être nettoyées en réglant tcp_zerowin_abort_interval$ sur N > 0. Les sockets seront nettoyées N secondes après la réception du prochain segment TCP avec une fenêtre zéro. Des sondes de fenêtre sont envoyées toutes les 100 secondes pour confirmer que la fenêtre de réception de l'hôte distant est toujours fermée, donc au pire une réponse sera reçue dans les 100 secondes. La valeur par défaut de tcp_zerowin_abort_interval$ est zéro et je suggère qu'elle reste à 0, à moins que vous ne deviez nettoyer une socket. À ce stade, je suggère de la fixer à une petite valeur, disons 10 secondes, et une fois que la socket est nettoyée, de la remettre à 0. Je pense que cela réduit le risque d'effacer des sockets qui sont récupérables

Pour définir cette valeur, vous devez utiliser la requête set_longword dans analyze_system, donc souvenez-vous que N sera en hexadécimal. Par exemple, pour le fixer à 10, la requête sera
set_longword tcp_zerowin_abort_interval$ a

2024 Stratus Technologies.