J'ai écrit un petit programme qui interagit avec un serveur sur un port spécifique. Le programme fonctionne bien, mais:
Une fois le programme terminé inopinément et depuis que cette connexion de socket est affichée dans l'état CLOSE_WAIT
. Si j'essaie d'exécuter un programme, il se bloque et je dois le forcer à fermer, ce qui accumule même les connexions de socket plus CLOSE_WAIT
.
Existe-t-il un moyen de vider ces connexions?
CLOSE_WAIT
signifie que votre programme est toujours en cours d'exécution et n'a pas fermé le socket (et le noyau attend qu'il le fasse). Ajoutez -p
à netstat
pour obtenir le pid, puis tuez-le plus énergiquement (avec SIGKILL
si nécessaire). Cela devrait vous débarrasser de vos sockets CLOSE_WAIT
. Vous pouvez également utiliser ps
pour trouver le pid.
SO_REUSEADDR
est pour les serveurs et TIME_WAIT
sockets, donc ne s'applique pas ici.
Comme décrit par Crist Clark .
CLOSE_WAIT signifie que l'extrémité locale de la connexion a reçu un FIN à partir de l'autre extrémité, mais le système d'exploitation attend le programme au fin locale pour réellement fermer sa connexion.
Le problème est que votre programme exécuté sur la machine locale n’est pas fermer la prise. Ce n'est pas un problème d'optimisation TCP. Une connexion peut (et tout à fait correctement) restez à CLOSE_WAIT pour toujours pendant le programme maintient la connexion ouverte.
Une fois que le programme local ferme le socket, le système d'exploitation peut envoyer le FIN à l'extrémité distante qui vous fait passer à LAST_ACK en attendant le ACK du FIN. Une fois que cela est reçu, la connexion est terminée et abandonne la table de connexion (si votre fin est dans CLOSE_WAIT, vous do not finissez dans l’état TIME_WAIT).
Même si trop de connexions CLOSE_WAIT signifient qu'il y a quelque chose qui ne va pas avec votre code dans le premier et que cela n'est pas une bonne pratique.
Vous voudrez peut-être consulter: https://github.com/rghose/kill-close-wait-connections
Ce script envoie un ACK que la connexion attendait.
C'est ce qui a fonctionné pour moi.
J'ai également le même problème avec un tout dernier serveur Tomcat (7.0.40). Il ne réagit pas une fois pendant quelques jours.
Pour voir les connexions ouvertes, vous pouvez utiliser:
Sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT
Comme mentionné dans cet article , vous pouvez utiliser /proc/sys/net/ipv4/tcp_keepalive_time
pour afficher les valeurs. La valeur semble être en secondes et la valeur par défaut est 7200 (soit 2 heures).
Pour les changer, vous devez éditer /etc/sysctl.conf
.
Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`
Il convient de mentionner que l’instance Socket
à la fois du client et du serveur doit appeler explicitement close()
. Si une seule des extrémités appelle close()
, le socket reste dans l'état CLOSE_WAIT.