Comment fonctionne `TIME_WAIT` côté serveur?

11

Je sais qu'il y a pas mal de questions SE à ce sujet, et je crois que j'en ai lu autant qu'il le faut avant d'en arriver là.

Par "côté serveur TIME_WAIT", j'entends l'état d'une paire de sockets côté serveur dont la fermeture () a été déclenchée côté serveur.

Je vois souvent ces déclarations qui me semblent contradictoires:

  1. Côté serveur TIME_WAITest inoffensif
  2. Vous devez concevoir vos applications réseau pour que les clients lancent close (), donc le client doit TIME_WAIT

La raison pour laquelle je trouve cela contradictoire est que TIME_WAITle client peut être un problème - le client peut manquer de ports disponibles, donc essentiellement ce qui précède recommande de déplacer la charge du TIME_WAITcôté client où il peut être problématique, du côté serveur où ce n'est pas un problème.

Le côté client TIME_WAITn'est bien sûr qu'un problème pour un nombre limité de cas d'utilisation. La plupart des solutions client-serveur impliqueraient un serveur et de nombreux clients, les clients ne traitent généralement pas avec un volume de connexions suffisamment élevé pour que ce soit un problème, et même s'ils le font, il existe un certain nombre de recommandations à "sainement" ( par opposition à SO_LINGER0 timeout, ou se mêler de tcp_tw sysctls) combattre côté client TIME_WAITen évitant de créer trop de connexions trop rapidement. Mais ce n'est pas toujours possible, par exemple pour une classe d'applications comme:

  • systèmes de surveillance
  • générateurs de charge
  • procurations

D'un autre côté, je ne comprends même pas du tout comment le côté serveur TIME_WAITest utile. La raison TIME_WAITest même là, car elle empêche d'injecter des TCPfragments périmés dans des flux auxquels ils n'appartiennent plus. Pour le côté client, TIME_WAITcela est accompli en rendant simplement impossible la création d'une connexion avec les mêmes ip:portpaires que cette connexion périmée aurait pu avoir (les paires utilisées sont verrouillées par TIME_WAIT). Mais pour le côté serveur, cela ne peut pas être évité car l'adresse locale aura le port d'acceptation, et sera toujours la même, et le serveur ne peut pas (AFAIK, je n'ai que la preuve empirique) refuser la connexion simplement parce que un homologue entrant créerait la même paire d'adresses qui existe déjà dans la table des sockets.

J'ai écrit un programme qui montre que TIME-WAIT côté serveur est ignoré. De plus, comme le test a été fait sur 127.0.0.1, le noyau doit avoir un bit spécial qui lui indique même si c'est du côté serveur ou côté client (car sinon le tuple serait le même).

Source: http://pastebin.com/5PWjkjEf , testé sur Fedora 22, configuration réseau par défaut.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Ainsi, pour le côté serveur TIME_WAIT, les connexions sur la même paire de ports peuvent être rétablies immédiatement et avec succès, et pour le côté client TIME-WAIT, la deuxième itération a connect()échoué correctement.

Pour résumer, la question est double:

  • Le côté serveur ne fait-il TIME_WAITvraiment rien et est-il laissé de cette façon parce que le RFCrequiert?
  • Est-ce la raison pour laquelle le client recommande d'initialiser close () parce que le serveur TIME_WAITest inutile?
Pawel Veselov
la source
Vous ne manquerez de ports que si vous n'avez qu'un seul client. Vous disposez de 65535 ports pour chaque combinaison d'IP client / serveur. La connexion depuis 1.2.3.4:1111 est différente de 4.3.2.1:1111. Il suffit de quelques octets de mémoire pour chaque connexion TIME_WAIT.
Marki555

Réponses:

1

En termes TCP , côté serveur signifie ici l'hôte qui a le socket en état LISTEN.

Le RFC1122 permet au socket dans l'état TIME-WAIT d'accepter une nouvelle connexion avec certaines conditions

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Pour plus de détails sur les conditions, veuillez consulter le RFC1122 . Je m'attends à ce qu'il y ait également un OPEN passif correspondant sur le socket (socket à l'état LISTEN).

OPEN actif (appel de connexion côté client) n'a pas une telle exception et doit donner une erreur lorsque le socket est en TIME-WAIT, conformément à RFC793 .

Ma supposition pour la recommandation sur le client (en termes TCP, l'hôte effectuant une ouverture active, c'est-à-dire une connexion) initiée, est à peu près la même que la vôtre, que dans le cas commun, elle répartit les sockets TIME-WAIT sur plus d'hôtes où il y a une abondance de ressources pour les prises. Dans le cas courant, les clients n'envoient pas de SYN qui réutiliseraient les sockets TIME-WAIT sur le serveur. J'accepte que l'application d'une telle recommandation dépend toujours du cas d'utilisation.

Marko Kohtala
la source
0

C'est probablement l'exemple le plus clair de ce que TIME-WAIT fait réellement et surtout pourquoi c'est important. Il explique également pourquoi éviter certains des conseils «experts» sur les machines Linux pour «réduire» les TIME-WAIT.

Khushil
la source
N'explique toujours pas ce qui se passe lorsqu'une connexion client-> serveur est initiée, et un serveur a cette paire verrouillée dans un TIME_WAIT
Pawel Veselov
Veuillez consulter stackoverflow.com/questions/1490196/… - la réponse est ce que vous cherchez.
Khushil
0

Une session TCP est identifiée par le tupple (sourceIP, sourcePort, destIP, destPort). Par conséquent, TIME_WAIT fonctionne sur chaque connexion TCP.

En ce qui concerne la fermeture, dans certains scénarios, la fermeture du côté client peut réduire les sockets TIME_WAIT sur le serveur, réduisant ainsi légèrement la mémoire. Dans les cas où l'espace de socket peut être épuisé (en raison de l'épuisement du port éphémère) (par exemple, les clients gourmands avec de nombreuses connexions au même serveur), ce problème doit être résolu de n'importe quel côté.

basos
la source
S'il vous plaît, expliquez; lorsque vous demandez si le TW côté serveur fait quelque chose, vous vous demandez si la même connexion peut être réutilisée pendant la période TW. La réponse est non car la connexion, telle que définie par le tupple, prend place dans la table tcp du serveur. Si le client essaie d'ouvrir la même connexion bientôt, il recevra un RST, refusant effectivement la connexion TCP. Soit dit en passant, l'article de Khushil est très descriptif.
basos
Je suis vraiment désolé, votre réponse répond effectivement à la question, je l'ai mal lu et j'ai retiré mon commentaire. Cependant, il semble également être incorrect, car j'ai du code qui semble prouver qu'il n'y a pas de protection côté serveur TIME_WAIT(j'ai mis à jour la question avec ces informations). La référence de @ Khushil ne couvre pas les TIME_WAITcas côté serveur avec suffisamment de détails.
Pawel Veselov
-2

Avec un protocole non fiable, vous ne pouvez jamais être sûr que vous avez reçu le dernier message de votre appareil homologue, il est donc dangereux de supposer que votre homologue a raccroché le téléphone assez soudainement. C'est un inconvénient majeur du protocole TCP que seuls 65 000 ports environ peuvent être ouverts simultanément. Mais la solution consiste à passer à une batterie de serveurs, qui s'adapte mieux à la charge, qu'en recyclant rapidement les numéros de port. Du côté client, il est très peu probable que vous manquiez de ports s'il s'agit d'un poste de travail de base.

jrrk
la source
Je suis vraiment désolé, mais cela ne répond pas à ma question.
Pawel Veselov