Eu sei que há algumas questões de SE sobre isso, e eu acredito que li o máximo possível antes de chegar a este ponto.
Por "lado do servidor TIME_WAIT
" refiro-me ao estado de um par de soquetes do lado do servidor que teve seu close () iniciado no lado do servidor.
Muitas vezes vejo essas declarações que parecem contraditórias para mim:
- Lado do servidor
TIME_WAIT
é inofensivo
- Você deve projetar seus aplicativos de rede para que os clientes iniciem perto (), portanto, ter o cliente carrega o
TIME_WAIT
A razão pela qual eu acho isso contraditório é porque TIME_WAIT
no cliente pode ser um problema - o cliente pode executar as portas disponíveis, então, em essência, o acima está recomendando mover a carga de TIME_WAIT
para o cliente lado onde pode ser problema, do lado do servidor, onde não é um problema.
O TIME_WAIT
do lado do cliente é, obviamente, apenas um problema para um número limitado de casos de uso. A maioria das soluções cliente-servidor envolveria um servidor e muitos clientes, os clientes normalmente não lidam com um volume suficientemente alto de conexões para que isso seja um problema, e mesmo se o fizerem, há várias recomendações para "sanear" ( ao contrário de SO_LINGER
com 0 timeout, ou de se intrometer nos sysctls tcp_tw, combata TIME_WAIT
do lado do cliente, evitando criar muitas conexões muito rapidamente. Mas isso nem sempre é viável, por exemplo, para classes de aplicativos como:
- sistemas de monitoramento
- geradores de carga
- proxies
Por outro lado, eu nem entendo como o TIME_WAIT
do lado do servidor é útil. A razão pela qual TIME_WAIT
está lá, é porque ela impede a injeção de fragmentos obsoletos TCP
em fluxos aos quais eles não mais pertencem. Para TIME_WAIT
do lado do cliente, isso é feito simplesmente tornando impossível criar uma conexão com os mesmos pares ip:port
que essa conexão obsoleta poderia ter tido (os pares usados são bloqueados por TIME_WAIT
). Mas para o lado do servidor, isso não pode ser evitado já que o endereço local terá a porta de aceitação, e sempre será o mesmo, e o servidor não pode (AFAIK, eu só tenho a prova empírica) negar a conexão simplesmente porque um par de entrada criaria o mesmo par de endereços que já existe na tabela de soquetes.
Eu escrevi um programa que mostra que TIME-WAIT do lado do servidor são ignorados. Além disso, como o teste foi feito em 127.0.0.1, o kernel deve ter um bit especial que até informa se é do lado do servidor ou do lado do cliente (caso contrário, a tupla seria a mesma).
Fonte: link , testado no Fedora 22, configuração de rede padrão.
$ 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
Assim, para TIME_WAIT
do lado do servidor, as conexões no mesmo par de portas podem ser restabelecidas imediatamente e com êxito, e para o lado do cliente TIME-WAIT
, na segunda iteração connect()
justamente reprovado
Para resumir, a pergunta é dupla:
- O
TIME_WAIT
do lado do servidor realmente não faz nada e é deixado assim porque o RFC
requer isso?
- O motivo é a recomendação para o cliente iniciar o close () porque o servidor
TIME_WAIT
é inútil?