Quando uma conexão TCP é fechada em uma extremidade da conexão - a outra extremidade recebe um FIN
e responde com um ACK
. Essa extremidade da conexão entra então no CLOSE_WAIT
estado. Uma vez close()
chamado neste final, o TCP envia um FIN
pacote e entra no LAST_ACK
estado. No entanto, nunca entra no TIME_WAIT
estado.
Agora, vamos supor que o Host A chame close()
o soquete e envie um FIN
pacote para o Host B. O Host A entra no FIN_WAIT_1
estado. O host B recebe o FIN
pacote, envia um ACK
e então entra no CLOSE_WAIT
estado. No entanto, o ACK é descartado em algum lugar de um roteador upstream.
Enquanto isso, o Host B chama close()
(lembre-se que o Host B está no CLOSE_WAIT
estado) e envia um FIN
pacote para o Host A. O Host B agora entra no LAST_ACK
estado. O Host A recebe o FIN
pacote e responde com um arquivo ACK
. Em seguida, entra no CLOSING
estado.
Na outra extremidade, o Host B ainda está no LAST_ACK
estado. Em seguida, ele recebe o ACK
do Host A e entra no CLOSED
estado. Lembre-se de que o ACK
host B para o Host A foi descartado e que o Host A não reenviou seu FIN
pacote. O Host A reenvia seu FIN
pacote após o tempo limite - no entanto, o Host B fechou a conexão.
O Host A agora está preso no CLOSING
estado? A desmontagem da conexão pode continuar? O que acontece depois?
Responder1
Meu TCP está um pouco enferrujado mas acredito que funcione assim:
Quando o Host B chama close()
e envia seu FIN
, o número de sequência FIN
revelará ao Host A que perdeu um pacote do Host B. Portanto, o Host A não confirmará o Host B FIN
, ele continuará confirmando o último segmento TCP que ele recebido com sucesso do Host B. Isso solicitará que o Host B retransmita o arquivo ACK
.
Portanto, o Host A não alcançará o CLOSING
estado, pois não considerará o fora de ordem FIN
como verdadeiramente recebido até receber a falta ACK
que o precedeu.