Sé que hay bastantes preguntas SE sobre esto, y creo que leí tantas como importa antes de llegar a este punto.
Por "lado del servidor TIME_WAIT
" me refiero al estado de un par de sockets del lado del servidor que tuvo su cierre () iniciado en el lado del servidor.
A menudo veo estas declaraciones que me parecen contradictorias:
- El lado del servidor
TIME_WAIT
es inofensivo - Debe diseñar sus aplicaciones de red para que los clientes inicien close (), por lo tanto, que el cliente lleve
TIME_WAIT
La razón por la que encuentro esto contradictorio es porque TIME_WAIT
el cliente puede ser un problema: el cliente puede quedarse sin puertos disponibles, por lo que, en esencia, lo anterior recomienda trasladar la carga TIME_WAIT
al lado del cliente donde puede ser un problema, desde el lado del servidor donde no es un problema.
El lado del cliente TIME_WAIT
es, por supuesto, solo un problema para un número limitado de casos de uso. La mayoría de las soluciones cliente-servidor involucrarían un servidor y muchos clientes, los clientes generalmente no manejan un volumen de conexiones lo suficientemente alto como para que sea un problema, e incluso si lo hacen, hay una serie de recomendaciones para "cuerdo" ( a diferencia de SO_LINGER
con 0 tiempo de espera, o entrometerse con tcp_tw sysctls) combata el lado del cliente TIME_WAIT
evitando crear demasiadas conexiones demasiado rápido. Pero eso no siempre es factible, por ejemplo, para clases de aplicaciones como:
- sistemas de monitoreo
- generadores de carga
- proxies
Por otro lado, ni siquiera entiendo cómo el lado del servidor TIME_WAIT
es útil en absoluto. La razón TIME_WAIT
está ahí, porque evita la inyección de TCP
fragmentos obsoletos en las secuencias a las que ya no pertenecen. Para el lado del cliente, TIME_WAIT
se logra simplemente haciendo imposible crear una conexión con los mismos ip:port
pares que podría haber tenido esta conexión obsoleta (los pares usados están bloqueados TIME_WAIT
). Pero para el lado del servidor, esto no se puede evitar, ya que la dirección local tendrá el puerto de aceptación, y siempre será la misma, y el servidor no puede (AFAIK, solo tengo la prueba empírica) negar la conexión simplemente porque un par entrante crearía el mismo par de direcciones que ya existe en la tabla de socket.
Escribí un programa que muestra que TIME-WAIT del lado del servidor se ignora. Además, debido a que la prueba se realizó en 127.0.0.1, el núcleo debe tener un bit especial que incluso le diga si es del lado del servidor o del lado del cliente (ya que de lo contrario la tupla sería la misma).
Fuente: http://pastebin.com/5PWjkjEf , probado en Fedora 22, configuración de red predeterminada.
$ 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
Entonces, para el lado del servidor TIME_WAIT
, las conexiones en el mismo par de puertos exactos podrían restablecerse de manera inmediata y exitosa, y para el lado del cliente TIME-WAIT
, en la segunda iteración connect()
fallaron correctamente
Para resumir, la pregunta es doble:
- ¿El lado del servidor
TIME_WAIT
realmente no hace nada, y simplemente se deja así porque loRFC
requiere? - ¿Es la razón por la que la recomendación es que el cliente inicie close () porque el servidor
TIME_WAIT
es inútil?
TIME_WAIT
.