No Linux (meus servidores ativos estão no RHEL 5.5 - os links LXR abaixo são para a versão do kernel), man 7 ip
diz:
Um endereço de soquete local TCP que foi vinculado fica indisponível por algum tempo após o fechamento, a menos que o sinalizador SO_REUSEADDR tenha sido definido.
Eu não estou usando SO_REUSEADDR
. Quanto tempo dura "algum tempo"? Como posso descobrir quanto tempo dura e como posso alterá-lo?
Eu estive pesquisando sobre isso e encontrei algumas informações, nenhuma das quais realmente explica isso da perspectiva de um programador de aplicativos. A saber:
- TCP_TIMEWAIT_LEN in
net/tcp.h
é "quanto tempo esperar para destruir o estado TIME-WAIT" e é corrigido em "cerca de 60 segundos" - / proc / sys / net / ipv4 / tcp_fin_timeout é "Hora de manter o soquete no estado FIN-WAIT-2, se foi fechado ao nosso lado" e "O valor padrão é 60seg"
Onde eu tropeço é fazer a ponte entre o modelo do kernel do ciclo de vida do TCP e o modelo de portas do programador indisponível, ou seja, para entender como esses estados se relacionam com o "algum tempo".
man 2 bind
se você não acredita em mim. É certo que provavelmente não é a primeira coisa que as pessoas do Unix pensam quando alguém diz "vincular", tão justo.bind
, mas a tag aqui é aplicada especificamente ao servidor DNS. Não temos tags para todas as chamadas de sistema possíveis.Respostas:
Acredito que a idéia de o soquete não estar disponível para um programa é permitir que qualquer segmento de dados TCP ainda em trânsito chegue e seja descartado pelo kernel. Ou seja, é possível que um aplicativo chame
close(2)
um soquete, mas atrasos de roteamento ou contratempos para controlar pacotes ou o que você pode permitir que o outro lado de uma conexão TCP envie dados por um tempo. O aplicativo indicou que não deseja mais lidar com segmentos de dados TCP, portanto o kernel deve descartá-los assim que chegarem.Eu criei um pequeno programa em C que você pode compilar e usar para ver quanto tempo o tempo limite é:
Eu tentei este programa em 3 máquinas diferentes e recebo um tempo variável, entre 55 e 59 segundos, quando o kernel se recusa a permitir que um usuário não root reabra um soquete. Compilei o código acima em um executável chamado "abridor" e executei-o assim:
Abri outra janela e fiz o seguinte:
Isso faz com que a primeira instância do "abridor" aceite uma conexão e feche-a. A segunda instância do "abridor" tenta
bind(2)
acessar a porta TCP 7896 a cada segundo. "abridor" relata 55 a 59 segundos de atraso.Pesquisando no Google, acho que as pessoas recomendam fazer isso:
para reduzir esse intervalo. Não funcionou para mim. Das 4 máquinas Linux que eu tinha acesso, duas tinham 30 e duas tinham 60. Também defini esse valor como 10. Não há diferença para o programa "opener".
Fazendo isso:
mudou as coisas. O segundo "abridor" levou apenas cerca de 3 segundos para obter seu novo soquete.
fonte