TCP TIME-WAIT & les serveurs Linux à fort trafic

Vincent Bernat

En bref

N’ac­ti­vez pas net.​ipv4.​tcp_​tw_​recycle (qui n’existe même plus de­puis Li­nux 4.12) ! La plu­part du temps, les connexions dans l’état TIME-WAIT sont in­of­fen­sives. Dans le cas contraire, sau­tez au ré­sumé pour les so­lu­tions re­com­mandées.

La do­cu­men­ta­tion du noyau Li­nux n’est pas très pro­lixe sur les ef­fets de net.​ipv4.​tcp_​tw_​recycle et de net.​ipv4.​tcp_​tw_​reuse. Ce manque de do­cu­men­ta­tion laisse la place à de très nom­breux guides conseillant d’ac­ti­ver ces deux pa­ra­mètres afin de se dé­ba­ras­ser des en­trées dans l’état TIME-WAIT. Tou­te­fois, comme in­di­qué dans la page de ma­nuel tcp(7), l’op­tion net.​ipv4.​tcp_​tw_​recycle peut s’avé­rer pro­blé­ma­tique car elle pré­sente des dif­fi­cul­tés à gé­rer cor­rec­te­ment des clients der­rière une même IP. Ce pro­blème est par­ti­cu­liè­re­ment dif­fi­cile à diag­nos­ti­quer quand il survient :

Ac­tive le re­cy­clage ra­pide des connexions dans l’état TIME-WAIT. Ac­ti­ver cette op­tion n’est pas re­com­mandé car elle cause des pro­blèmes avec la trans­la­tion d’adresses (NAT).

Dans l’es­poir de ren­ver­ser la ten­dance, je four­nis ici une ex­pli­ca­tion plus dé­taillée sur le fonc­tion­ne­ment de l’état TIME-WAIT dans Li­nux. Gar­dez à l’es­prit que nous nous in­té­res­sons à la pile TCP de Li­nux qui n’a qua­si­ment au­cun lien avec le suivi de connexions de Net­filter1.

À propos de l’état TIME-WAIT#

Com­men­çons d’abord par com­prendre com­ment fonc­tionne l’état TIME-WAIT et les pro­blèmes qu’il peut po­ser. Re­gar­dons le dia­gramme d’état TCP ci-dessous :

Diagramme d'état TCP
Diagramme d’état TCP

Seul l’hôte fer­mant la connexion en pre­mier se re­trouve dans l’état TIME-WAIT. L’autre pair suit un che­min qui conduit gé­né­ra­le­ment à la li­bé­ra­tion com­plète et ra­pide de la connexion.

La com­mande ss -tan per­met d’ob­ser­ver l’état de toutes les connexions sur le système :

$ ss -tan | head -5
LISTEN     0  511             *:80              *:*
SYN-RECV   0  0     192.0.2.145:80    203.0.113.5:35449
SYN-RECV   0  0     192.0.2.145:80   203.0.113.27:53599
ESTAB      0  0     192.0.2.145:80   203.0.113.27:33605
TIME-WAIT  0  0     192.0.2.145:80   203.0.113.47:50685

Mission#

L’état TIME-WAIT a deux buts :

  • Le pre­mier est d’em­pê­cher les seg­ments en re­tard d’être ac­cep­tés dans une connexion uti­li­sant le même qua­dru­plet (adresse source, port source, adresse cible, port cible). La RFC 1337 ex­plique en dé­tail ce qui peut ar­ri­ver si l’état TIME-WAIT ne joue pas son rôle. Voici un exemple de ce qui peut être évité si l’état TIME-WAIT n’est pas raccourci :
Segments dupliqués acceptés dans une autre connexion
En raison d’un état TIME-WAIT trop bref, un segment TCP en retard est accepté dans une connexion sans rapport.
  • Le se­cond but est d’as­su­rer que l’hôte dis­tant a bien fermé la connexion. Lorsque que le der­nier ACK est perdu, l’hôte dis­tant reste dans l’état LAST-ACK2. Si l’état TIME-WAIT n’exis­tait pas, une connexion vers cet hôte pour­rait être ten­tée. Le seg­ment SYN peut alors être ac­cueilli avec un RST. La nou­velle connexion se ter­mine alors avec une erreur :
Dernier ACK perdu
Lorsque le pair distant reste dans l’état LAST-ACK, ouvrir une nouvelle connexion avec le même quadruplet échoue.

La RFC 793 de­mande à ce que l’état TIME-WAIT dure au moins deux fois le MSL. Sur Li­nux, cette du­rée n’est pas confi­gu­rable. Elle est dé­fi­nie dans include/​net/​tcp.h et vaut une minute :

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
                                  * state, about 60 seconds     */

Il y a eu des pro­po­si­tions pour rendre ce pa­ra­mètre confi­gu­rable mais celles-ci ont été re­je­tées en rai­son de la né­ces­sité de conser­ver le bon fonc­tion­ne­ment de l’état TIME-WAIT.

Problèmes#

Voyons main­te­nant pour­quoi cet état peut de­ve­nir en­nuyeux sur un ser­veur gé­rant de nom­breuses connexions. Il y a trois as­pects à considérer :

  • l’en­trée prise dans la table des connexions et em­pê­chant de nou­velles connexions ;
  • la mé­moire oc­cu­pée par la so­cket dans le noyau ;
  • l’usage CPU ad­di­tionnel.

Le ré­sul­tat de la com­mande ss -tan state time-wait | wc -l n’est pas un pro­blème en soi !

Table des connexions#

Une connexion dans l’état TIME-WAIT est gar­dée pen­dant une mi­nute dans la table des connexions. Cela si­gni­fie qu’une connexion avec le même qua­dru­plet (adresse source, port source, adresse des­ti­na­tion, port des­ti­na­tion) ne peut pas exister.

Pour un ser­veur web, l’adresse des­ti­na­tion et le port des­ti­na­tion sont constants. Si ce ser­veur se si­tue en plus der­rière un ré­par­ti­teur de charge L7, l’adresse IP source est éga­le­ment constante. Li­nux al­loue par dé­faut les ports pour les connexions sor­tantes dans un in­ter­valle d’en­vi­ron 30 000 ports (cela se règle en mo­di­fiant net.​ipv4.​ip_​local_​port_​range). Chaque mi­nute, au plus 30 000 connexions peuvent donc être éta­blies vers le ser­veur web, soit en­vi­ron 500 connexions par seconde.

Mise à jour (10.2026)

Cette li­mite est moins stricte quand les chaus­settes dans l’état TIME-WAIT se trouvent côté ser­veur. Li­nux ac­cepte un nou­veau seg­ment SYN pour un qua­dru­plet dans l’état TIME-WAIT si son nu­méro de sé­quence est su­pé­rieur au der­nier reçu pour la connexion pré­cé­dente, comme le per­met la RFC 1122, ou si son ho­ro­da­tage est plus ré­cent, comme le dé­crit la RFC 6191.

Si l’état TIME-WAIT se si­tue côté client, une telle si­tua­tion se dé­tecte fa­ci­le­ment. L’ap­pel à connect() re­tourne EADDRNOTAVAIL et l’ap­pli­ca­tion va jour­na­li­ser l’er­reur. Côté ser­veur, la si­tua­tion est plus com­plexe à dé­cé­ler. Dans le doute, il convient de sa­voir me­su­rer s’il y a sa­tu­ra­tion des qua­dru­plets dis­ponibles :

$ ss -tan 'sport = :80' | awk '{print $(NF)" "$(NF-1)}' | \
>     sed 's/:[^ ]*//g' | sort | uniq -c
    696 10.24.2.30 10.33.1.64
   1881 10.24.2.30 10.33.1.65
   5314 10.24.2.30 10.33.1.66
   5293 10.24.2.30 10.33.1.67
   3387 10.24.2.30 10.33.1.68
   2663 10.24.2.30 10.33.1.69
   1129 10.24.2.30 10.33.1.70
  10536 10.24.2.30 10.33.1.73

La so­lu­tion à ces pro­blèmes est d’uti­li­ser plus de qua­dru­plets3. Il y a plu­sieurs so­lu­tions (par ordre de dif­ficulté) :

  • uti­li­ser plus de ports clients en mo­di­fiant net.​ipv4.​ip_​local_​port_range ;
  • uti­li­ser plus de ports ser­veurs en confi­gu­rant le ser­veur web pour écou­ter sur des ports sup­plé­men­taires (81, 82, 83, …) ;
  • uti­li­ser plus d’IP clients en confi­gu­rant des IP sup­plé­men­taires sur le ré­par­ti­teur de charge et en les uti­li­sant l’une après l’autre4 ;
  • uti­li­ser plus d’IP ser­veurs en confi­gu­rant des IP sup­plé­men­taires sur le ser­veur web5.

Une der­nière so­lu­tion est de mo­di­fier net.​ipv4.​tcp_​tw_​reuse et net.​ipv4.​tcp_​tw_​recycle. Pa­tien­tez en­core un peu, nous y ar­ri­ve­rons plus tard.

Mémoire#

Avec beau­coup de connexions à gé­rer, gar­der des en­trées in­ac­tives pen­dant une mi­nute oc­cupe de la mé­moire. Par exemple, si un ser­veur gère 10 000 connexions par se­conde, il peut y avoir en per­ma­nence 600 000 en­trées TIME-WAIT. Quelle quan­tité de mé­moire cela re­pré­sente-t-il ? Pas tant que ça.

Tout d’abord, côté ap­pli­ca­tif, une connexion en TIME-WAIT n’existe plus. Elle a été fer­mée. Dans le noyau, une connexion dans l’état TIME-WAIT est ma­té­ria­li­sée à trois en­droits pour trois usages dif­férents :

  1. La table de ha­chage des connexions, ap­pe­lée la « table des connexions TCP éta­blies » (bien qu’elle contienne des connexions dans un autre état), per­met de lo­ca­li­ser une connexion exis­tante lors, par exemple, de la ré­cep­tion d’un nou­veau segment.

    Chaque en­trée de cette table pointe sur deux listes : une liste des connexions dans l’état TIME-WAIT et une liste des connexions dans un autre état. La taille de cette table dé­pend de la quan­tité de mé­moire sur le sys­tème et est in­di­quée lors du dé­marrage :

    $ dmesg | grep "TCP established hash table"
    [    0.169348] TCP established hash table entries: 65536 (order: 8, 1048576 bytes)
    

    Il est pos­sible de spé­ci­fier soi-même la taille avec le pa­ra­mètre thash_​entries.

    Chaque élé­ment de la liste des connexions dans l’état TIME-WAIT est de type struct tcp_​timewait_​sock, tan­dis que les élé­ments de l’autre liste sont de type struct tcp_sock6 :

    struct tcp_timewait_sock {
        struct inet_timewait_sock tw_sk;
        u32    tw_rcv_nxt;
        u32    tw_snd_nxt;
        u32    tw_rcv_wnd;
        u32    tw_ts_offset;
        u32    tw_ts_recent;
        long   tw_ts_recent_stamp;
    };
    
    struct inet_timewait_sock {
        struct sock_common  __tw_common;
    
        int                     tw_timeout;
        volatile unsigned char  tw_substate;
        unsigned char           tw_rcv_wscale;
        __be16 tw_sport;
        unsigned int tw_ipv6only     : 1,
                     tw_transparent  : 1,
                     tw_pad          : 6,
                     tw_tos          : 8,
                     tw_ipv6_offset  : 16;
        unsigned long            tw_ttd;
        struct inet_bind_bucket *tw_tb;
        struct hlist_node        tw_death_node;
    };
    
  2. Un en­semble de listes de connexions ap­pelé le « cou­loir de la mort ». Il est uti­lisé pour ex­pi­rer les connexions dans l’état TIME-WAIT. Les connexions sont or­don­nées sui­vant la date d’ex­piration.

    Ces connexions uti­lisent le même es­pace mé­moire que pour les en­trées dans la table de ha­chage dé­crite au point pré­cé­dent. Il s’agit du membre struct hlist_​node tw_​death_node7.

  3. Une table de ha­chage des ports lo­caux uti­li­sés per­met de dé­ter­mi­ner ou de trou­ver ra­pi­de­ment un port lo­cal pour une nou­velle connexion. La taille de cette table est la même que la table de ha­chage des connexions :

    $ dmesg | grep "TCP bind hash table"
    [    0.169962] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
    

    Chaque élé­ment est de type struct inet_​bind_​bucket qui cor­res­pond à un port lo­cal. Une connexion dans l’état TIME-WAIT vers un ser­veur web cor­res­pond au port lo­cal 80 et par­tage donc son en­trée avec les autres connexions du même type. D’un autre côté, chaque connexion sor­tante uti­lise un port lo­cal aléa­toire et ne par­tage donc gé­né­ra­le­ment pas son entrée.

Chaque connexion (en­trante ou sor­tante) a donc be­soin d’un struct tcp_​timewait_​sock De plus, chaque connexion sor­tante est at­ta­chée à un struct inet_​bind_​bucket dédié.

La taille d’un struct tcp_​timewait_​sock est de 168 oc­tets tan­dis qu’un struct inet_​bind_​bucket oc­cupe 48 octets :

$ sudo apt-get install linux-image-$(uname -r)-dbg
[…]
$ gdb /usr/lib/debug/boot/vmlinux-$(uname -r)
(gdb) print sizeof(struct tcp_timewait_sock)
 $1 = 168
(gdb) print sizeof(struct tcp_sock)
 $2 = 1776
(gdb) print sizeof(struct inet_bind_bucket)
 $3 = 48

Ainsi, 40 000 connexions en­trantes dans l’état TIME-WAIT oc­cupent en­vi­ron 10 Mio alors que 40 000 connexions sor­tantes oc­cupent en plus 2,5 Mio. L’uti­li­taire slabtop per­met de confir­mer ce cal­cul. Voyez ce qui est in­di­qué pour un ser­veur avec 50 000 connexions dans l’état TIME-WAIT dont 45 000 connexions sortantes :

$ sudo slabtop -o | grep -E '(^  OBJS|tw_sock_TCP|tcp_bind_bucket)'
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
 50955  49725  97%    0.25K   3397       15     13588K tw_sock_TCP
 44840  36556  81%    0.06K    760       59      3040K tcp_bind_bucket

Il n’y a rien à mo­di­fier ici : la mé­moire oc­cu­pée par les connexions dans l’état TIME-WAIT est très faible. Si votre ser­veur doit gé­rer des mil­liers de nou­velles connexions par se­conde, la mé­moire né­ces­saire pour pou­voir pous­ser ef­fi­ca­ce­ment les don­nées rend la pré­sence des connexions dans l’état TIME-WAIT né­gligeable.

CPU#

Côté CPU, la re­cherche d’un port lo­cal de libre est ef­fec­tué par la fonc­tion inet_​csk_​get_​port() qui em­ploie un ver­rou et uti­lise la table de ha­chage des ports lo­caux jusqu’à trou­ver un port libre. Un très grand nombre d’en­trées dans cette table n’im­pacte gé­né­ra­le­ment pas les per­for­mances car si les connexions sont re­la­ti­ve­ment ho­mo­gènes, cette fonc­tion par­court les ports lo­caux de ma­nière sé­quen­tielle et re­tourne donc ra­pi­de­ment un résultat.

Autres solutions#

Ar­rivé à ce point, si vous pen­sez tou­jours avoir un pro­blème avec l’état TIME-WAIT, il existe trois autres so­lutions :

  • désac­ti­ver le so­cket lingering,
  • net.​ipv4.​tcp_​tw_reuse,
  • net.​ipv4.​tcp_​tw_​recycle.

Socket lingering#

Lorsque close() est ap­pelé, les oc­tets res­tants dans le noyau se­ront en­voyés en tâche de fond et la connexion ter­mi­nera dans l’état TIME-WAIT. L’ap­pli­ca­tion ré­cu­père im­mé­dia­te­ment la main avec la cer­ti­tude que les don­nées fi­ni­ront par être livrées.

Tou­te­fois, une ap­pli­ca­tion peut désac­ti­ver ce com­por­te­ment (connu sous le nom so­cket lin­ge­ring). Il y a deux pos­si­bilités :

  1. La pre­mière est de désac­ti­ver en­tiè­re­ment le mé­ca­nisme. Les don­nées res­tantes se­ront per­dues et la connexion est ter­mi­née par l’en­voi d’un seg­ment RST. L’hôte dis­tant dé­tec­tera alors une er­reur. La connexion ne pas­sera pas par l’état TIME-WAIT.

  2. La se­conde est d’at­tendre un cer­tain temps que les don­nées soient li­vrées et seule­ment en­suite de cas­ser la connexion comme dans le point pré­cé­dent. L’ap­pel à close() est alors blo­quant jusqu’à ce que les don­nées soient li­vrées ou que le dé­lai dé­fini soit écoulé. Il est pos­sible d’évi­ter ce blo­quage en pas­sant la connexion en mode non blo­quant. Le pro­ces­sus s’ef­fec­tue alors en tâche de fond. Si les don­nées sont li­vrées avec suc­cès, la connexion pas­sera dans l’état TIME-WAIT. Dans le cas contraire, un seg­ment RST sera en­voyé et les don­nées se­ront perdues.

Dans les deux cas, désac­ti­ver le so­cket lin­ge­ring n’est pas une so­lu­tion uni­ver­selle. Cer­taines ap­pli­ca­tions telles que HAProxy ou Nginx peuvent em­ployer sous cer­taines condi­tions une telle tech­nique mais cela n’est pas sys­té­matique.

net.​ipv4.​tcp_​tw_​reuse#

L’état TIME-WAIT per­met d’évi­ter que des seg­ments en re­tard ne soient ac­cep­tés dans une connexion dif­fé­rente. Tou­te­fois, sous cer­taines condi­tions, il est pos­sible de dif­fé­ren­cier de ma­nière cer­taine les seg­ments d’une connexion pré­cé­dente des seg­ments d’une connexion actuelle.

La RFC 1323 in­tro­duit un en­semble d’ex­ten­sions pour amé­lio­rer les per­for­mances de TCP. Parmi celles-ci, on trouve l’ho­ro­da­tage sous forme de deux mar­queurs : l’un cor­res­pond à l’hor­loge de l’ex­pé­di­teur et l’autre au mar­queur le plus ré­cent reçu par ce dernier.

En ac­ti­vant net.​ipv4.​tcp_​tw_​reuse, Li­nux va réuti­li­ser une connexion dans l’état TIME-WAIT pour une nou­velle connexion sor­tante à condi­tion que la date soit stric­te­ment plus grande que la der­nière date uti­li­sée pour l’an­cienne connexion (ce qui cor­res­pond le plus sou­vent à une se­conde de dif­férence).

Est-ce sûr ? Le pre­mier but de l’état TIME-WAIT est d’évi­ter que des seg­ments du­pli­qués soient ac­cep­tés dans une connexion dif­fé­rente. L’usage de l’ho­ro­da­tage per­met d’évi­ter ce pro­blème car les seg­ments en ques­tion ar­ri­ve­ront avec un mar­queur trop vieux et se­ront ignorés.

Le se­cond but est de s’as­su­rer que l’hôte dis­tant ne se trouve pas dans l’état LAST-ACK suite à la perte du der­nier seg­ment ACK. L’hôte dis­tant re­trans­met le seg­ment FIN jusqu’à ce qu’une des condi­tions sui­vantes se réalise :

  1. ex­pi­ra­tion de l’état ;
  2. ré­cep­tion du seg­ment ACK attendu ;
  3. ré­cep­tion d’un seg­ment RST.

Dans tous les cas, la connexion est en­suite dé­truite. Si les seg­ments FIN ainsi en­voyés sont re­çus alors que l’état TIME-WAIT existe tou­jours, le ACK at­tendu sera re­transmis.

Lorsque l’état TIME-WAIT est rem­placé par une nou­velle connexion, l’ho­ro­da­tage ga­ran­tit que le seg­ment SYN de la nou­velle connexion sera ignoré et qu’un nou­veau seg­ment FIN sera ren­voyé. Ce seg­ment FIN ar­ri­vant pour une connexion dé­sor­mais dans l’état SYN-SENT, il re­ce­vra en ré­ponse un seg­ment RST qui per­met­tra de sor­tir de l’état LAST-ACK. Le seg­ment SYN ini­tia­le­ment ignoré sera re­trans­mis au bout d’une se­conde (car il n’a pas eu de ré­ponse) et la connexion sera alors éta­blie sans er­reur ap­pa­rente en de­hors du dé­lai d’une seconde :

Dernier ACK perdu et réutilisation du TIME-WAIT
Si le pair distant est dans l’état LAST-ACK, il pourra en sortir lors de la réception d’un segment RST.

À no­ter que chaque connexion ainsi réuti­li­sée im­plique l’in­cré­ment du comp­teur TWRecycled (mal­gré son nom).

net.​ipv4.​tcp_​tw_​recycle#

Ce mé­ca­nisme s’ap­puie éga­le­ment sur l’ho­ro­da­tage des seg­ments mais in­fluence à la fois les connexions en­trantes et les connexions sor­tantes ce qui est utile quand les états TIME-WAIT s’ac­cu­mulent côté serveur8.

L’état TIME-WAIT va ex­pi­rer plus tôt : il sera sup­primé après écou­le­ment du dé­lai de re­trans­mis­sion (RTO) qui est cal­culé à par­tir du RTT et de sa va­riance. Les va­leurs en ques­tion peuvent être ob­te­nues pour les connexions en cours avec la com­mande ss :

$ ss --info  sport = :2112 dport = :4057
State      Recv-Q Send-Q    Local Address:Port        Peer Address:Port
ESTAB      0      1831936   10.47.0.113:2112          10.65.1.42:4057
         cubic wscale:7,7 rto:564 rtt:352.5/4 ato:40 cwnd:386 ssthresh:200 send 4.5Mbps rcv_space:5792

Afin de ga­ran­tir les mêmes pro­prié­tés four­nies par l’état TIME-WAIT tout en gar­dant cet état moins long­temps, quand une connexion at­teint l’état TIME-WAIT, le der­nier ho­ro­da­tage ob­servé est en­re­gis­tré dans une struc­ture dé­diée avec l’IP de l’hôte dis­tant concerné. Li­nux igno­rera alors pen­dant une mi­nute tout seg­ment pro­ve­nant d’un hôte connu mais dont l’ho­ro­da­tage est en contra­dic­tion avec la va­leur mé­morisée :

if (tmp_opt.saw_tstamp &&
    tcp_death_row.sysctl_tw_recycle &&
    (dst = inet_csk_route_req(sk, &fl4, req, want_cookie)) != NULL &&
    fl4.daddr == saddr &&
    (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) {
        inet_peer_refcheck(peer);
        if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
            (s32)(peer->tcp_ts - req->ts_recent) >
                                        TCP_PAWS_WINDOW) {
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                goto drop_and_release;
        }
}

Lorsque plu­sieurs hôtes par­tagent une même IP (cou­rant avec du NAT), cette condi­tion les em­pêche de pou­voir se connec­ter car ils n’uti­lisent pas la même hor­loge pour l’ho­ro­da­tage. Dans le doute, il est donc pré­fé­rable de ne pas ac­ti­ver cette op­tion car elle conduit à des pro­blèmes dif­fi­ciles à dé­tec­ter et dif­fi­ciles à diag­nostiquer.

Mise à jour (09.2017)

À par­tir de Li­nux 4.10 (com­mit 95a22caee396), Li­nux uti­lise un dé­ca­lage aléa­toire pour l’ho­ro­da­tage de chaque connexion. Cela casse en­tiè­re­ment cette op­tion, NAT ou pas. Elle a été re­ti­rée de Li­nux 4.12.

L’état LAST-ACK est géré de la même fa­çon que dans le cas de net.​ipv4.​tcp_​tw_reuse.

Résumé#

La so­lu­tion uni­ver­selle est d’aug­men­ter le nombre de com­bi­nai­sons pos­sibles pour les qua­dru­plets en uti­li­sant, par exemple, plu­sieurs ports côté serveur.

Côté ser­veur, ne ja­mais ac­ti­ver net.​ipv4.​tcp_​tw_​recycle en rai­son des ef­fets de bord. Ac­ti­ver net.​ipv4.​tcp_​tw_​reuse est sans ef­fet sur les connexions en­trantes.

Côté client, ac­ti­ver net.​ipv4.​tcp_​tw_​reuse est une so­lu­tion qua­si­ment fiable. Ac­ti­ver en plus net.​ipv4.​tcp_​tw_​recycle est alors quasi-inutile.

De plus, lors de la concep­tion d’un pro­to­cole, ne pas lais­ser un client fer­mer la connexion en pre­mier. La ges­tion de l’état TIME-WAIT sera re­pous­sée sur les ser­veurs qui ont un large éven­tail de so­lu­tions pour y faire face.

Pour ter­mi­ner, voici une ci­ta­tion de W. Ri­chard Ste­vens is­sue de Unix Net­work Pro­gramming:

L’état TIME_​WAIT est notre ami et est là pour nous ai­der (c.-à-d. per­mettre aux seg­ments du­pli­qués d’ex­pi­rer en tran­sit). Plu­tôt que de ten­ter de sup­pri­mer cet état, nous de­vons le com­prendre.

Mise à jour (10.2026)

Cet ar­ticle a été briè­ve­ment dis­cuté sur Ha­cker News.