Sous Linux (mes serveurs en direct sont sur RHEL 5.5 - les liens LXR ci-dessous sont vers la version du noyau), man 7 ip
dit:
Une adresse de socket local TCP qui a été liée n'est pas disponible pendant un certain temps après la fermeture, sauf si l'indicateur SO_REUSEADDR a été défini.
Je n'utilise pas SO_REUSEADDR
. Combien de temps dure "un certain temps"? Comment savoir combien de temps il dure et comment le changer?
J'ai fait des recherches sur ce sujet et j'ai trouvé quelques morceaux d'informations, dont aucun n'explique vraiment cela du point de vue d'un programmeur d'applications. En être témoin:
- TCP_TIMEWAIT_LEN en
net/tcp.h
est « combien de temps attendre pour détruire l' état TIME-WAIT », et est fixé à « environ 60 secondes » - / proc / sys / net / ipv4 / tcp_fin_timeout est "Time to hold socket in state FIN-WAIT-2, if it was closed by our side", et "Default value is 60sec"
Là où je trébuche, c'est pour combler le fossé entre le modèle du noyau du cycle de vie TCP et le modèle de programmeur des ports qui ne sont pas disponibles, c'est-à-dire pour comprendre comment ces états sont liés au "quelque temps".
man 2 bind
si vous ne me croyez pas. Certes, ce n'est probablement pas la première chose à laquelle les gens d'Unix pensent quand quelqu'un dit "lier", donc assez juste.bind
, mais la balise ici est spécifiquement appliquée au serveur DNS. Nous n'avons pas de balises pour chaque appel système possible.Réponses:
Je crois que l'idée que le socket n'est pas disponible pour un programme est de permettre à tous les segments de données TCP encore en transit d'arriver et d'être rejetés par le noyau. Autrement dit, il est possible pour une application d'appeler
close(2)
sur un socket, mais les retards ou les incidents de routage pour contrôler les paquets ou ce que vous avez peuvent permettre à l'autre côté d'une connexion TCP d'envoyer des données pendant un certain temps. L'application a indiqué qu'elle ne souhaitait plus traiter les segments de données TCP, le noyau devrait donc simplement les supprimer à mesure qu'ils entrent.J'ai piraté un petit programme en C que vous pouvez compiler et utiliser pour voir combien de temps le timeout est:
J'ai essayé ce programme sur 3 machines différentes, et j'obtiens un temps variable, entre 55 et 59 secondes, lorsque le noyau refuse d'autoriser un utilisateur non root à rouvrir un socket. J'ai compilé le code ci-dessus dans un exécutable nommé "opener" et l'ai exécuté comme ceci:
J'ai ouvert une autre fenêtre et j'ai fait ceci:
Cela oblige la première instance de "opener" à accepter une connexion, puis à la fermer. La seconde instance de "opener" essaie de
bind(2)
se connecter au port TCP 7896 chaque seconde. "ouvreur" signale 55 à 59 secondes de retard.Googler autour, je trouve que les gens recommandent de faire ceci:
pour réduire cet intervalle. Ça n'a pas marché pour moi. Sur les 4 machines Linux auxquelles j'avais accès, deux en avaient 30 et deux en avaient 60. J'ai également réglé cette valeur à 10. Aucune différence avec le programme "opener".
Ce faisant:
a changé les choses. Le deuxième "ouvreur" n'a pris que 3 secondes environ pour obtenir sa nouvelle prise.
la source