Hipótese 1: seu aplicativo está por trás de um firewall que desconecta conexões tcp ociosas após um determinado período de tempo.
Quando o cliente tenta usar essa conexão novamente, ele não responde, solta e inicia um novo.
Para o servidor, como as conexões TCP não possuem um temporizador de manutenção, não há como saber se a conexão é inválida e se permanecerá aberta indefinidamente.
Para provar: faça um tcpdump de execução longa de uma conexão para mostrar que ele não é utilizado após um determinado período de tempo.
Solução:
- Altere o código para usar o keep-alive nos soquetes tcp e (opcionalmente, para um melhor desempenho) defina o cronômetro de keep-alive como menor que o temporizador tcp-idle do firewall
- Altere o temporizador tcp-idle do firewall para um valor mais alto além do tempo ocioso máximo funcional do cliente. Muito provavelmente, essa será uma configuração global no firewall, portanto, o administrador de segurança pode estar relutante em fazer isso.