Problema
A aplicação apresenta erros de conexão com o banco de dados, e em alguns casos, pode resultar na interrupção do Pool de Aplicativos do IIS, devido a erros na inicialização da aplicação.
Nessa situação, a mensagem a seguir poderá ser observada nos logs de arquivo de texto:
System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted
A mensagem também pode ser apresentada em português:
System.Net.Sockets.SocketException: Normalmente é permitida apenas uma utilização de cada endereço de soquete (protocolo/endereço de rede/porta)
Causa
De forma resumida, este erro ocorre quando o Windows não tem mais portas dinâmicas disponíveis para estabelecer uma nova comunicação TCP/IP. Neste caso, uma comunicação de rede entre servidor de aplicação e de banco de dados.
Conexão em estado TIME_WAIT
Embora as conexões com o banco de dados estejam sendo encerradas corretamente pela aplicação, a comunicação entre os dois computadores não é finalizada imeditamente. Ela continua estabelecida, porém em estado TIME_WAIT.
As conexões em estado TIME_WAIT podem ser verificadas com o seguinte comando:
netstat -a
Mesmo encerrando a aplicação no IIS, as conexões continuarão em estado TIME_WAIT, pois quem gerencia isso é o Sistema Operacional, e não a aplicação.
Por padrão, o Windows aguarda entre 2 e 4 minutos para encerrar conexões no estado TIME_WAIT.
Intervalo de portas dinâmicas
Ao tentar estabelecer uma nova conexão TCP/IP (neste caso com o servidor de banco de dados), o Window utiliza uma porta dinâmica disponível. Porém o número de portas que podem ser utilizadas nesta operação é limitado.
O intervalo de portas dinâmicas definido para o protocolo TCP pode ser verificado com a seguinte linha de comando:
netsh int ipv4 show dynamicport tcp
Esgotamento de Portas
Uma porta dinâmica usada em uma conexão TCP/IP entre dois computadores não poderá ser reutilizada enquanto a conexão estiver em estado TIME_WAIT.
Eventualmente, com o acúmulo de conexões neste estado, ocorrerá o esgotamento de portas dinâmicas, o que levará a ocorrência dos erros.
Solução
Existem 3 soluções que podem ser usadas combinadas ou individualmente para solucionar o problema:
Utilizar Pooling de Conexões
Usando o Pool de Conexões, você terá um número menor de novas conxões sendo abertas, e consequentemente, vai ser mais difícil esgotar o número de portas dinâmicas.
Mais informações neste tópico: Pooling de Conexões
Reduzir o tempo de TIME_WAIT
Reduzindo o tempo de TIME_WAIT, a porta bloqueada será liberada mais cedo, e consequentemente, vai ser mais difícil esgotar o número de portas dinâmicas.
Para definir TcpTimedWaitDelay (tempo limite do TIME_WAIT):
-
Use o comando
regedit
para acessar a subchave do registroHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters
. -
Crie um novo valor
REG_DWORD
chamado “TcpTimedWaitDelay”, e defina o valor como30
(segundos). -
Crie um novo valor
REG_DWORD
chamado “StrictTimeWaitSeqCheck”, e defina o valor como1
. -
Reinicie o sistema.
Aumentar o intervalo de portas dinâmicas
Aumentando o número de portas dinâmicas, será possível ter mais conexões simultâneas em estado TIME_WAIT.
Para definir MaxUserPort (intervalo de portas dinâmicas):
-
Use o comando
regedit
para acessar a subchave do registroHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters
. -
Crie um novo valor
REG_DWORD
chamado “MaxUserPort”. -
Defina esse valor como
65534
(máximo). -
Reinicie o sistema.
Mais informações aqui: Only one usage of each socket address (protocol/network address/port) is normally permitted | Microsoft Learn