Question

Je pense que je comprends le sens formel de l'option. Dans certains code héritage que je me occupe maintenant, l'option est utilisée. Le client se plaint de la TVD en réponse à FIN de son côté à la fermeture de connexion de son côté.

Je ne suis pas sûr que je peux le retirer en toute sécurité, puisque je ne comprends pas quand il doit être utilisé.

Pouvez-vous s'il vous plaît donner un exemple quand serait nécessaire l'option?

Était-ce utile?

La solution

La raison typique de définir un délai de SO_LINGER de zéro est d'éviter un grand nombre de connexions assis dans l'état TIME_WAIT, liant toutes les ressources disponibles sur un serveur.

Quand une connexion TCP est fermée proprement, la fin qui a initié la fermeture ( « close active ») se termine avec la connexion assis dans TIME_WAIT pendant plusieurs minutes. Donc, si votre protocole est celui où le serveur initie la proximité de la connexion, et implique un très grand nombre de connexions de courte durée, alors il pourrait être sensible à ce problème.

Ce n'est pas une bonne idée, mais - TIME_WAIT existe pour une raison (pour faire en sorte que les paquets parasites de vieilles connexions ne pas interférer avec les nouvelles connexions). Il est une meilleure idée de revoir le protocole à une situation où le client initie la connexion de proximité de, si possible.

Autres conseils

Pour ma suggestion, s'il vous plaît lire la dernière section. « Quand utiliser SO_LINGER avec délai d'attente 0 »

Avant de passer à cette une petite conférence sur:

  • terminaison normale TCP
  • TIME_WAIT
  • FIN, ACK et RST

terminaison normale TCP

Les regards normaux de séquence de terminaison TCP comme celui-ci (simplifié):

Nous avons deux pairs: A et B

  1. A appelle close()
    • A envoie FIN à B
    • Un passe en état FIN_WAIT_1
  2. B reçoit FIN
    • B envoie ACK à A
    • B va dans l'état de CLOSE_WAIT
  3. A reçoit ACK
    • Un passe en état FIN_WAIT_2
  4. B appelle close()
    • B envoie FIN à A
    • B va dans l'état de LAST_ACK
  5. A reçoit FIN
    • A envoie ACK à B
    • Un passe en état TIME_WAIT
  6. B reçoit ACK
    • B passe à l'état de CLOSED - à-dire est éliminé à partir des tables de socket

TIME_WAIT

Ainsi, le pair qui initie la terminaison - à savoir les appels close() premier -. Finira dans l'état TIME_WAIT

Pour comprendre pourquoi l'état TIME_WAIT est notre ami, s'il vous plaît lire la section 2.7 dans "Réseau UNIX Programmation" troisième édition par Stevens et al (page 43).

Cependant, il peut être un problème avec beaucoup de prises dans l'état de TIME_WAIT sur un serveur car il pourrait éventuellement empêcher de nouvelles connexions soient acceptés.

Pour contourner ce problème, je l'ai vu beaucoup qui suggère de définir l'option de prise SO_LINGER avec délai d'attente avant d'appeler 0 close(). Cependant, cela est une mauvaise solution car il provoque la connexion TCP à se terminer par une erreur.

Au lieu de cela, la conception de votre protocole d'application de sorte que la terminaison de connexion est toujours lancée à partir du côté client. Si le client sait toujours quand il a lu toutes les données restantes il peut lancer la séquence de terminaison. À titre d'exemple, un navigateur sait de l'Content-Length en-tête HTTP quand il a lu toutes les données et peut initier la fermeture. (Je sais que dans HTTP 1.1 il garder ouvert pendant un certain temps pour une réutilisation possible, puis fermez-le.)

Si les besoins du serveur pour fermer la connexion, la conception du protocole d'application de sorte que le serveur demande au client à l'appel close().

Quand utiliser SO_LINGER avec délai d'attente 0

Encore une fois, selon « Réseau UNIX Programmation » troisième édition, page 202-203, mise en SO_LINGER avec délai d'attente 0 avant d'appeler close() provoquera la séquence de terminaison normale pas pour être initié.

Au lieu de cela, le PAIRS cette option et appeler close() enverra un RST (réinitialisation de la connexion) qui indique une condition d'erreur, ce qui est la façon dont il sera perçu à l'autre bout. Vous généralement voir des erreurs comme « Connexion réinitialisée par les pairs ».

Par conséquent, dans la situation normale, il est une très mauvaise idée de jeu SO_LINGER avec délai d'attente 0 avant d'appeler close() - désormais appelé close avortée -. Dans une application serveur

Cependant, certains bons de souscription de la situation faisant de toute façon:

  • Si le client de votre application serveur (se comporte mal, renvoie fois sur des données non valides, etc.), un proche avorté est logique d'éviter d'être coincé dans CLOSE_WAIT ou de se retrouver dans l'état TIME_WAIT.
  • Si vous devez redémarrer votre application serveur qui a actuellement des milliers de connexions client que vous pourriez envisager de définir cette option de socket afin d'éviter des milliers de prises de serveur dans TIME_WAIT (lorsque vous appelez close() de la fin du serveur), cela pourrait empêcher le serveur d'obtenir les ports disponibles pour de nouvelles connexions client après avoir été redémarré.
  • Sur la page 202 dans le livre mentionné ci-dessus, il dit expressément: « Il y a certaines circonstances qui justifient d'utiliser cette fonction pour envoyer un proche avorté Un exemple est un serveur de terminal RS-232, qui peut se bloquer à jamais dans CLOSE_WAIT essayer de fournir des données. à un port de terminal bloqué, mais il réinitialiser correctement le port bloqué si elle a un RST pour rejeter les données en attente ».

Je recommande

Si vous pouvez supprimer le Linger dans votre code dépend en toute sécurité ou non du type de votre demande: est-il un « client » (connexions TCP d'ouverture et de fermeture activement en premier) ou est-il un « serveur » (écouter un TCP ouvert et le fermer après l'autre côté initié la fin)?

Si votre application a la saveur d'un « client » (fermeture en premier) et vous initier et fermer un grand nombre de connexions à différents serveurs (par exemple, lorsque votre application est une application de surveillance supervisant la joignabilité d'un grand nombre de serveurs différents ) votre application a le problème que toutes vos connexions clientes sont coincés dans l'état TIME_WAIT. Ensuite, je recommande de raccourcir le délai d'attente à une valeur inférieure à la valeur par défaut pour toujours l'arrêt grâce, mais libérer les connexions client ressources plus tôt. Je ne mettrais pas le délai d'attente à 0, comme 0 n'a pas l'arrêt gracieusement avec FIN mais avortée avec RST.

Si votre application a la saveur d'un « client » et doit chercher une énorme quantité de petits fichiers à partir du même serveur, vous ne devriez pas lancer une nouvelle connexion TCP par fichier et finir par une énorme quantité de connexions clients dans TIME_WAIT, mais gardez la connexion ouverte et chercher toutes les données sur la même connexion. l'option Linger peut et doit être supprimé.

Si votre application est un « serveur » (deuxième position en réaction à la clôture de pairs), à proximité () votre connexion est à l'arrêt sont libérés grâce et des ressources comme vous ne saisissez pas l'état TIME_WAIT. Linger ne doit pas être utilisé. Mais si votre application sever a un processus de surveillance détectant les connexions ouvertes inactives idleing depuis longtemps ( « long » est à définir), vous pouvez arrêter cette connexion inactive de votre côté - voir comme une sorte de gestion des erreurs - avec un arrêt avorté. Cela se fait par la mise en temporisation linger à 0. close () enverra alors un RST au client, en lui disant que vous êtes en colère: -)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top