Quelle est la signification de SO REUSEADDR (option setsockopt) - Linux? [dupliquer]
cette question a déjà une réponse ici:
- Socket options SO_REUSEADDR et SO_REUSEPORT, en quoi diffèrent-elles? Signifient-ils les mêmes dans tous les principaux systèmes d'exploitation? 1 réponse
à Partir de la page de man:
spécifie SO_REUSEADDR que les règles utilisé pour valider les adresses fournies de bind() devrait permettre la réutilisation de locaux les adresses, si elles sont supportées par protocole. Cette option prend un int valeur. C'est une option booléenne
Quand dois-je l'utiliser? Pourquoi" réutiliser les adresses locales"?
3 réponses
le but principal de la conception de TCP est de permettre une communication fiable des données face à la perte de paquets, à la réorganisation de paquets et - ici - à la duplication de paquets.
c'est assez évident comment une pile réseau TCP/IP gère tout cela pendant que la connexion est en haut, mais il y a un cas de bord qui se produit juste après la fermeture de la connexion. Que se passe-t-il si un paquet envoyé juste à la fin de la conversation est dupliqué et retardé, de sorte que l'arrêt à 4 voies Les paquets arrivent au récepteur avant le paquet retardé? La pile ferme consciencieusement sa connexion. Puis plus tard, le paquet de duplicata retardé apparaît. Que doit faire la pile?
plus important encore, que doit-il faire si le programme propriétaire de cette connexion meurt immédiatement, alors un autre commence à vouloir la même adresse IP et le même numéro de port TCP?
Il y a un couple de choix:
-
ne permet pas de réutiliser ce combo IP/port pendant au moins deux fois la durée maximale de vol d'un paquet. Dans TCP, cela est généralement appelé le délai 2× MSL . Vous voyez aussi parfois 2× RTT , ce qui est à peu près équivalent.
c'est le comportement par défaut de toutes les piles TCP/IP courantes. 2×MSL est typiquement entre 30 et 120 secondes. (C'est la période
TIME_WAIT
.) Après ce temps, le stack suppose que n'importe quels paquets voyous ont été abandonnés en route en raison de périmé TTLs , de sorte qu'il laisse l'étatTIME_WAIT
, permettant que le combo IP/port soit réutilisé. -
permettent au nouveau programme de se lier de nouveau à ce combo IP/port. En piles avec BSD sockets interfaces-essentiellement tous les Unixes et Unix-like systems, Plus Windows via Winsock - vous devez demander ce comportement en paramétrant l'option
SO_REUSEADDR
viasetsockopt()
avant d'appelerbind()
.
SO_REUSEADDR
est le plus souvent défini dans les programmes de serveur.
la raison est, un motif commun est que vous changez un fichier de configuration de serveur et besoin de redémarrer ce serveur pour le faire recharger sa configuration. Sans SO_REUSEADDR
, le bind()
l'appel dans la nouvelle instance du programme redémarré échouera s'il y avait des connexions ouvertes à l'instance précédente quand vous l'avez tué. Ces connexions retiendront le port TCP dans l'état TIME_WAIT
pendant 30-120 secondes, donc vous tombez dans le cas 1 ci-dessus.
la chose sûre à faire est d'attendre la période TIME_WAIT
, mais en pratique ce n'est pas un risque assez grand que cela vaut la peine de faire cela. Il est préférable d'obtenir le serveur de retour immédiatement afin de ne pas manquer plus les connexions entrantes que nécessaire.
SO_REUSEADDR permet à votre serveur de lier à une adresse qui est dans un
TIME_WAIT state.
cette option de socket indique au noyau que même si ce port est occupé (dans L'état TIME_WAIT), allez de l'avant et réutilisez-le quand même. S'il est occupé, mais avec un autre État, vous obtiendrez toujours une adresse déjà en erreur d'utilisation. Il est utile si votre serveur a été arrêté, puis redémarré tout de suite alors que les sockets sont toujours actif sur son port.
quand vous créez une socket, vous ne la possédez pas vraiment. Le système d'exploitation (pile TCP) crée pour vous et vous donne une poignée (descripteur de fichier) pour y accéder. Lorsque votre socket est fermé, il faut du temps pour que L'OS "le ferme complètement" alors qu'il passe par plusieurs États. Comme EJP l'a mentionné dans les commentaires, le délai le plus long est généralement à partir de L'état TIME_WAIT. Ce délai supplémentaire est nécessaire pour traiter les bordures à la toute fin de la séquence de terminaison et s'assurer que la dernière terminaison l'accusé de réception est passé ou l'autre côté s'est réinitialisé à cause d'un temps mort. ici vous pouvez trouver quelques considérations supplémentaires sur cet état. Les principales considérations sont les suivantes :
rappelez-vous que TCP garantit que toutes les données transmises seront livrées, si à tout possible. Lorsque vous fermez une socket, le serveur va dans un TIME_WAIT state, juste pour être vraiment sûr que toutes les données ont disparu travers. Quand une socket est fermée, les deux côtés acceptent en envoyant des messages les uns aux autres qu'ils n'enverront plus de données. Cela, c' il m'a semblé que c'était assez bien, et après la poignée de main est fait, le socket doit être fermé. Le problème est de deux ordres. Tout d'abord, il n'y a pas de façon d'être sûr que le dernier ack a été communiqué avec succès. Deuxièmement, il peut y avoir des "doublons errants" laissés sur le net qui doivent être traités s'ils sont livrés.
si vous essayez de créer plusieurs sockets avec la même adresse ip:port pair très rapidement, vous obtenez l'erreur "address already in use" parce que la socket précédente n'aura pas été entièrement libérée. L'utilisation de SO_REUSEADDR éliminera cette erreur car elle annulera les vérifications de n'importe quelle instance précédente.