Eu sei que existem algumas perguntas sobre SE e acredito que li tantas delas quanto antes antes de chegar a esse ponto.
Por "lado do servidor TIME_WAIT
", quero dizer o estado de um par de soquetes do lado do servidor que teve seu close () iniciado no lado do servidor.
Costumo ver estas afirmações que me parecem contraditórias:
- O lado do servidor
TIME_WAIT
é inofensivo - Você deve projetar seus aplicativos de rede para que os clientes iniciem close (), fazendo com que o cliente suporte os
TIME_WAIT
A razão pela qual considero isso contraditório é porque TIME_WAIT
o cliente pode ser um problema - o cliente pode ficar sem portas disponíveis; portanto, em essência, o acima recomendado é transferir a carga do TIME_WAIT
lado do cliente para onde ele pode ser um problema, a partir do lado do servidor onde não é um problema.
TIME_WAIT
Obviamente, o lado do cliente é 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. Geralmente, os clientes não lidam com um volume de conexões suficientemente alto para que isso seja um problema e, mesmo se o fizerem, há várias recomendações para "sanear". em oposição a SO_LINGER
com tempo limite 0, ou se intrometendo com tcp_tw sysctls) combate o lado do cliente, TIME_WAIT
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 lado do servidor TIME_WAIT
é útil. O motivo TIME_WAIT
está aí, porque evita a injeção de TCP
fragmentos obsoletos em fluxos aos quais eles não pertencem mais. Para o lado do cliente, TIME_WAIT
isso é feito simplesmente impossibilitando a criação de uma conexão com os mesmos ip:port
pares que essa conexão obsoleta poderia ter (os pares usados são bloqueados por TIME_WAIT
). Mas para o servidor, isso não pode ser evitado, pois o endereço local terá a porta de aceitação e sempre será o mesmo, e o servidor não pode (AFAIK, eu tenho apenas a prova empírica) negar a conexão simplesmente porque um ponto de entrada criaria o mesmo par de endereços que já existe na tabela de soquetes.
Eu escrevi um programa que mostra que o TIME-WAIT do lado do servidor é ignorado. Além disso, como o teste foi realizado no 127.0.0.1, o kernel deve ter um bit especial que informa se é do lado do servidor ou do cliente (caso contrário, a tupla seria a mesma).
Fonte: http://pastebin.com/5PWjkjEf , 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
Portanto, para o lado do servidor TIME_WAIT
, as conexões exatamente no mesmo par de portas podem ser restabelecidas imediatamente e com êxito e, para o lado do cliente TIME-WAIT
, na segunda iteração, a connect()
falha com retidão
Para resumir, a pergunta é dupla:
- O lado do servidor
TIME_WAIT
realmente não faz nada e é deixado assim porque oRFC
requer? - É por isso que a recomendação é que o cliente inicie close () porque o servidor
TIME_WAIT
é inútil?
TIME_WAIT
.Respostas:
Em termos de TCP , lado do servidor aqui significa o host que possui o soquete no estado LISTEN.
O RFC1122 permite que o soquete no estado TIME-WAIT aceite uma nova conexão com algumas condições
Para detalhes exatos sobre as condições, consulte o RFC1122 . Eu esperaria que também deve haver um OPEN passivo correspondente no soquete (soquete no estado LISTEN).
O OPEN ativo (chamada de conexão do lado do cliente) não possui essa exceção e deve dar erro quando o soquete estiver no TIME-WAIT, conforme RFC793 .
Meu palpite para a recomendação do cliente (em termos de TCP, o host executando OPEN ativo, isto é, conectar) iniciado próximo é praticamente o mesmo que o seu, que, no caso comum, ele espalha os soquetes TIME-WAIT em mais hosts, onde há abundância de recursos para as tomadas. No caso comum, os clientes não enviam SYN que reutilizariam os soquetes TIME-WAIT no servidor. Concordo que a aplicação de tal recomendação ainda depende do caso de uso.
fonte
Este é provavelmente o exemplo mais claro do que o TIME-WAIT realmente faz e, mais importante, por que é importante. Ele também explica por que evitar algumas dicas 'especializadas' em máquinas Linux para 'reduzir' o tempo de espera.
fonte
Uma sessão tcp é identificada pelo tupple (sourceIP, sourcePort, destIP, destPort). Portanto, o TIME_WAIT funciona em todas as conexões TCP.
Em relação ao lado de fechamento, em alguns cenários, o fechamento do lado do cliente pode reduzir os soquetes TIME_WAIT no servidor, reduzindo um pouco a memória. Nos casos em que o espaço do soquete pode ser esgotado (devido ao esgotamento efêmero da porta) (por exemplo, clientes gananciosos com muitas conexões com o mesmo servidor), esse problema deve ser resolvido de qualquer lado.
fonte
TIME_WAIT
(atualizei a pergunta com essas informações). A referência do @ Khushil não cobreTIME_WAIT
casos do lado do servidor com detalhes suficientes.Você nunca pode ter certeza, com um protocolo não confiável, de que recebeu a última mensagem do seu dispositivo ponto a ponto, portanto, é perigoso supor que ele tenha desligado o telefone repentinamente. É uma grande desvantagem do protocolo TCP que apenas 65000 ou mais portas possam ser abertas simultaneamente. Mas a maneira de superar isso seria mudar para um farm de servidores, que se adapta melhor à carga, do que reciclando números de portas rapidamente. No final do cliente, é altamente improvável que você fique sem portas se for uma estação de trabalho básica.
fonte